行为型设计模式:策略、观察者与责任链实战解析
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/10/13 17:24:21 阅读更多 →
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/10/3 20:59:20 阅读更多 →
C++ emplace_back 与 push_back 详解

C++ emplace_back 与 push_back 详解

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

2026/10/2 6:43:18 阅读更多 →

最新新闻

iMX8M异构多核开发:A53与M4的Rpmsg核间通信全解析

iMX8M异构多核开发:A53与M4的Rpmsg核间通信全解析

拿到一块iMX8M板卡,A53那边跑着Linux做业务逻辑,M4这边想跑FreeRTOS管实时控制,第一个绕不开的问题就是:这两个核之间到底怎么通信。我在实际项目里试过几种土办法——共享变量太脆弱,串口又太慢,敲了半天代…

2026/10/14 20:53:22 阅读更多 →
802.11-2020 PDF高效阅读指南:条款定位与测试基线实战

802.11-2020 PDF高效阅读指南:条款定位与测试基线实战

简介:此PDF为IEEE 802.11-2020标准的正式版全文,属于无线局域网领域的核心规范,面向网络工程师、通信专业学生与科研人员,用于理解WLAN介质访问控制层与物理层的完整定义。该版本由IEEE计算机协会LAN/MAN标准委员会开发&#xff0…

2026/10/14 20:53:22 阅读更多 →
ArcGIS Pro 2.5发布OSGB三维模型失败原因与修复指南

ArcGIS Pro 2.5发布OSGB三维模型失败原因与修复指南

1. 为什么OSGB在ArcGIS Pro 2.5里突然“变难了”——从模型加载到服务发布的断层真相你是不是也遇到过这样的情况:用ContextCapture或Pix4D生成的OSGB倾斜摄影模型,在本地ArcGIS Pro里打开时缩放流畅、纹理清晰,连瓦片层级切换都丝滑&#xf…

2026/10/14 20:53:22 阅读更多 →
Wing 模拟器中的 sim.Container:从 entrypoint 测试快照看自定义容器启动与底层实现

Wing 模拟器中的 sim.Container:从 entrypoint 测试快照看自定义容器启动与底层实现

编程语言编译器云原生语言运行时 【免费下载链接】wing A programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡ 项目地址: https://gitcode.com/gh_mirrors/wi/wing 点击查看 免…

2026/10/14 20:53:22 阅读更多 →
JDK 11.0.15 Linux部署指南:TLS 1.3与GC调优实战

JDK 11.0.15 Linux部署指南:TLS 1.3与GC调优实战

简介:本资源为Linux平台下Java 11.0.15正式版JDK标准发行包(jdk-11.0.15_linux-x64_bin.tar.gz),面向Java初学者、Linux服务器开发者及需要稳定LTS版本JDK的生产环境部署人员,解决跨平台开发、服务端编译运行及JVM调优…

2026/10/14 20:53:22 阅读更多 →
Dubbo服务注册与暴露全流程解析:从Spring容器启动到注册中心

Dubbo服务注册与暴露全流程解析:从Spring容器启动到注册中心

1. 从一次线上故障说起&#xff1a;为什么要搞清楚服务注册与暴露很多同学用 Dubbo 做微服务&#xff0c;配置文件里写个<dubbo:service>或者加个DubboService注解&#xff0c;服务就能被调用了&#xff0c;至于背后发生了什么&#xff0c;基本靠“框架自动搞定”这句话糊…

2026/10/14 20:52:20 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起&#xff1a;它到底想解决什么问题第一次看到"AnyPS5"这个标题&#xff0c;我脑子里冒出来的第一个念头是&#xff1a;这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述&#xff1a;Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师&#xff0c;我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性&#xff0c;实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景&#xff0c;也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间&#xff0c;确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中&#xff0c;这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/14 7:53:34 阅读更多 →