行为型设计模式:策略、观察者与责任链实战解析
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; } }

相关新闻

stltostp:零依赖STL到STEP转换引擎的技术重构与工业应用价值

stltostp:零依赖STL到STEP转换引擎的技术重构与工业应用价值

stltostp:零依赖STL到STEP转换引擎的技术重构与工业应用价值 【免费下载链接】stltostp Convert stl files to STEP brep files 项目地址: https://gitcode.com/gh_mirrors/st/stltostp 在数字化制造与工业设计领域,格式壁垒一直是阻碍数据流畅传…

2026/9/18 18:26:06 阅读更多 →
Traymond:Windows系统托盘窗口管理的高效解决方案

Traymond:Windows系统托盘窗口管理的高效解决方案

Traymond:Windows系统托盘窗口管理的高效解决方案 【免费下载链接】traymond A simple Windows app for minimizing windows to tray icons 项目地址: https://gitcode.com/gh_mirrors/tr/traymond 你是否曾在处理多个应用程序时感到桌面混乱不堪&#xff1f…

2026/9/19 17:49:09 阅读更多 →
C++ emplace_back 与 push_back 详解

C++ emplace_back 与 push_back 详解

一、核心区别对比项push_backemplace_back参数接受一个已存在的对象接受构造函数的参数过程先构造对象,再拷贝到容器直接在容器中构造对象效率可能产生临时对象和拷贝零拷贝,最高效一句话总结:push_back是“插入对象”,emplace_ba…

2026/9/14 10:15:06 阅读更多 →

最新新闻

Enzyme ReactWrapper 的 `.render()` 方法:把已挂载组件转为 HTML 后用 Cheerio 断言

Enzyme ReactWrapper 的 `.render()` 方法:把已挂载组件转为 HTML 后用 Cheerio 断言

测试前端 【免费下载链接】enzyme JavaScript Testing utilities for React 项目地址: https://gitcode.com/gh_mirrors/en/enzyme 点击查看 免费下载 本指南围绕 Enzyme 中 ReactWrapper.prototype.render() 方法展开,它能把当前 ReactWrapper 所包裹单…

2026/9/20 2:04:38 阅读更多 →
GD32H759工业HMI开发:SDRAM、SDIO与触摸屏调试实战

GD32H759工业HMI开发:SDRAM、SDIO与触摸屏调试实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 2:04:38 阅读更多 →
BIOS/UEFI固件原理与实战:从启动协议到Win11兼容性调优

BIOS/UEFI固件原理与实战:从启动协议到Win11兼容性调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 2:04:38 阅读更多 →
2025年Git自建服务器方案对比与Gitea实操指南

2025年Git自建服务器方案对比与Gitea实操指南

你有没有认真想过一个问题:代码放在别人的服务器上,真的完全踏实吗?我经常被问到“Git自建用什么工具比较好”,尤其是2025年的现在,各大托管平台的免费额度越来越抠,隐私合规的要求越来越多,团队…

2026/9/20 2:04:38 阅读更多 →
ARIS业务架构入门:EPC模型建模与模型治理完整指南

ARIS业务架构入门:EPC模型建模与模型治理完整指南

简介:《ARIS业务架构快捷入门手册》是一份面向ARIS初学者、业务流程分析师及需要快速上手业务架构建模的读者的实操型指南,重点解决安装配置、建模入口、对象与连接管理三个层面的常见问题。文档从先决条件与基本设置讲起,依次说明启动ARIS业…

2026/9/20 2:04:38 阅读更多 →
Aider 的 DeepSeek 通道改到 TaoToken,repo map 和 auto-commit 还照样跑吗?

Aider 的 DeepSeek 通道改到 TaoToken,repo map 和 auto-commit 还照样跑吗?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 2:03:38 阅读更多 →

日新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/19 23:01:36 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →