尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

行为型设计模式:策略、观察者与责任链实战解析

行为型设计模式:策略、观察者与责任链实战解析 1. 行为型模式的核心价值与定位在软件工程领域设计模式是解决特定场景下重复出现问题的经典方案。行为型模式作为三大模式类别之一创建型、结构型、行为型主要关注对象间的职责分配和算法抽象。与创建型模式关注对象实例化、结构型模式关注对象组合不同行为型模式通过定义对象间的交互方式使系统在运行时获得更高的灵活性。我在实际项目中最深刻的体会是行为型模式的价值在于解耦。当多个对象需要协作完成复杂业务逻辑时直接硬编码交互关系会导致牵一发而动全身。比如电商系统中的订单处理流程如果直接将库存服务、支付服务、物流服务的调用逻辑写在订单类中任何服务的接口变更都会迫使订单类修改。而通过行为型模式我们可以将这些交互关系抽象为独立对象使系统像乐高积木一样可灵活重组。2. 策略模式动态切换算法族2.1 模式结构与典型实现策略模式定义了一系列算法并将每个算法封装起来使它们可以互相替换。其UML类图通常包含三个核心角色Context环境类持有一个Strategy的引用Strategy抽象策略定义算法接口ConcreteStrategy具体策略实现具体算法以电商促销场景为例我们可以这样实现// 抽象策略 interface DiscountStrategy { double applyDiscount(double originalPrice); } // 具体策略 class VIPDiscount implements DiscountStrategy { Override public double applyDiscount(double price) { return price * 0.8; // VIP八折 } } class NewUserDiscount implements DiscountStrategy { Override public double applyDiscount(double price) { return price * 0.9; // 新用户九折 } } // 环境类 class Order { private DiscountStrategy strategy; public void setStrategy(DiscountStrategy strategy) { this.strategy strategy; } public double checkout(double price) { return strategy.applyDiscount(price); } }2.2 实战中的模式变体在实际开发中策略模式常与工厂模式结合使用。我曾在一个跨国电商项目中遇到需要根据用户地域自动选择计价策略的需求。解决方案是创建策略工厂根据用户IP自动返回对应的税率计算策略class StrategyFactory { public static DiscountStrategy createStrategy(User user) { if (user.isVIP()) { return new VIPDiscount(); } else if (user.isNew()) { return new NewUserDiscount(); } return new DefaultDiscount(); } }关键经验策略对象通常应该是无状态的可以被多个Context共享。如果需要维护状态应考虑在Context中保存状态而非策略中。3. 观察者模式事件驱动的解耦艺术3.1 推模型与拉模型对比观察者模式定义了对象间一对多的依赖关系当一个对象状态改变时所有依赖它的对象都会得到通知。根据数据传递方式不同分为推模型主题主动将详细数据推送给观察者拉模型主题仅通知观察者观察者主动拉取所需数据在分布式系统中我推荐使用拉模型。曾在一个物联网项目中设备状态变更服务采用推模型导致网络带宽激增改为拉模型后性能提升40%# 拉模型实现示例 class Sensor: def __init__(self): self._observers [] def attach(self, observer): self._observers.append(observer) def notify(self): for observer in self._observers: observer.update(self) # 传递self引用 def get_state(self): return self._internal_state class Display: def update(self, sensor): state sensor.get_state() # 观察者按需获取数据 self.render(state)3.2 现实项目中的挑战与解决方案在微服务架构下直接实现观察者模式会遇到服务间耦合问题。我的实践方案是使用消息队列如Kafka作为中间层定义统一的事件契约实现重试和死信机制例如订单状态变更通知// 事件定义 public class OrderEvent { private String orderId; private OrderStatus status; private long timestamp; // getters/setters } // 生产者 RestController class OrderController { Autowired private KafkaTemplateString, OrderEvent kafkaTemplate; PostMapping(/orders/{id}/status) public void updateStatus(PathVariable String id, RequestBody StatusUpdate update) { OrderEvent event new OrderEvent(id, update.getStatus()); kafkaTemplate.send(order-events, id, event); } } // 消费者 KafkaListener(topics order-events) public void handleOrderEvent(OrderEvent event) { inventoryService.updateStock(event); notificationService.sendAlert(event); }4. 责任链模式灵活处理请求管道4.1 纯责任链与不纯责任链责任链模式将请求的发送者和接收者解耦使多个对象都有机会处理请求。根据处理方式分为纯责任链请求必须被某个处理器处理不纯责任链请求可以被部分处理或传递在审批流系统中我设计过这样的处理链interface Handler { setNext(handler: Handler): Handler; handle(request: ApprovalRequest): ApprovalResult; } abstract class AbstractHandler implements Handler { private nextHandler: Handler; setNext(handler: Handler): Handler { this.nextHandler handler; return handler; } handle(request: ApprovalRequest): ApprovalResult { if (this.nextHandler) { return this.nextHandler.handle(request); } return { status: REJECTED, reason: No handler available }; } } class ManagerHandler extends AbstractHandler { handle(request: ApprovalRequest): ApprovalResult { if (request.amount 5000) { return { status: APPROVED, by: Manager }; } return super.handle(request); } } class DirectorHandler extends AbstractHandler { handle(request: ApprovalRequest): ApprovalResult { if (request.amount 20000) { return { status: APPROVED, by: Director }; } return super.handle(request); } }4.2 动态链构建技巧在Spring项目中可以利用依赖注入动态构建责任链Configuration class ChainConfig { Bean Order(1) public Handler firstHandler() { return new FirstHandler(); } Bean Order(2) public Handler secondHandler() { return new SecondHandler(); } Bean public HandlerChain handlerChain(ListHandler handlers) { // 自动按Order排序的handlers return new DefaultHandlerChain(handlers); } }性能提示责任链模式可能带来性能开销特别是在长链情况下。可以通过以下方式优化使用缓存记录每个请求适合的处理器对处理器进行性能分析将高频处理器前置对确定会拒绝的请求提前终止5. 模板方法模式算法骨架的标准化5.1 钩子方法的精妙运用模板方法模式在父类中定义算法骨架允许子类重写特定步骤。钩子方法Hook是模板方法模式的进阶技巧它提供默认空实现子类可选择性地覆盖。在数据导出功能中我设计了这样的模板abstract class DataExporter { // 模板方法 public final void Export(string path) { ValidatePath(path); var data LoadData(); data TransformData(data); if (NeedCompression()) { // 钩子方法 data Compress(data); } SaveToFile(data, path); PostExport(); // 钩子方法 } protected virtual bool NeedCompression() false; protected virtual void PostExport() { } protected abstract IEnumerableobject LoadData(); protected abstract byte[] TransformData(IEnumerableobject data); private void SaveToFile(byte[] data, string path) { File.WriteAllBytes(path, data); } } class CustomerExporter : DataExporter { protected override bool NeedCompression() true; protected override void PostExport() { StatsTracker.Increment(CustomerExport); } protected override IEnumerableobject LoadData() { return dbContext.Customers.ToList(); } protected override byte[] TransformData(IEnumerableobject data) { return JsonSerializer.SerializeToUtf8Bytes(data); } }5.2 防止子类破坏模板的防御技巧在实践中需要防止子类意外破坏模板方法的流程控制。我总结的防御方案包括将模板方法声明为finalJava/C#或不可覆盖C使用私有方法封装不变部分添加模板流程校验逻辑例如在支付流程中abstract class PaymentProcessor { public final void process(PaymentRequest request) { validateRequest(request); preProcess(request); PaymentResult result executePayment(request); postProcess(request, result); if (shouldLog(request)) { auditLog(request, result); } } private void validateRequest(PaymentRequest request) { Objects.requireNonNull(request); if (request.amount 0) { throw new IllegalArgumentException(Invalid amount); } } protected abstract PaymentResult executePayment(PaymentRequest request); protected void preProcess(PaymentRequest request) {} protected void postProcess(PaymentRequest request, PaymentResult result) {} protected boolean shouldLog(PaymentRequest request) { return true; } }
返回列表