设计模式详解——观察者模式一、模式概述1. 模式定义观察者模式Observer Pattern也叫发布-订阅模式Publish-Subscribe Pattern是一种行为型设计模式。它定义对象间一种一对多的依赖关系一一个主题被观察者多多个观察者当主题对象的状态发生改变时所有依赖它的观察者都会收到通知并自动更新。2. 核心思想一对多依赖松耦合被观察者只管发布通知不关心谁在监听观察者只管订阅并响应不关心谁发出事件状态变化自动传播无需主动轮询3. 主要角色抽象主题Subject提供注册、移除、通知观察者的接口具体主题ConcreteSubject维护状态状态变化时通知所有观察者抽象观察者Observer定义收到通知后的更新接口具体观察者ConcreteObserver实现更新逻辑处理自身业务客户端Client创建主题与观察者建立订阅关系二、适用场景一个对象状态改变需要自动通知其他多个对象系统需要解耦发布方与订阅方事件驱动、消息广播、状态同步场景框架中的事件机制、监听机制典型业务场景订单状态变更通知用户、物流、库存商品降价提醒聊天室消息推送配置变更实时生效前端事件监听、Spring 事件模型三、实战代码实现模拟订单状态通知场景说明订单状态改变时需要同时通知用户短信/APP推送物流系统准备发货库存系统扣减完成使用观察者模式实现一对多通知。1. 抽象观察者/** * 抽象观察者 */publicinterfaceObserver{// 收到通知后执行的方法voidupdate(StringorderStatus);}2. 具体观察者 A用户通知publicclassUserObserverimplementsObserver{Overridepublicvoidupdate(StringorderStatus){System.out.println(【用户通知】订单状态更新orderStatus已推送APP消息);}}3. 具体观察者 B物流系统publicclassLogisticsObserverimplementsObserver{Overridepublicvoidupdate(StringorderStatus){if(已支付.equals(orderStatus)){System.out.println(【物流系统】准备打包发货);}}}4. 具体观察者 C库存系统publicclassStockObserverimplementsObserver{Overridepublicvoidupdate(StringorderStatus){if(已支付.equals(orderStatus)){System.out.println(【库存系统】确认扣减库存完成);}}}5. 抽象主题importjava.util.List;/** * 抽象主题被观察者 */publicinterfaceSubject{// 注册观察者voidattach(Observerobserver);// 移除观察者voiddetach(Observerobserver);// 通知所有观察者voidnotifyObservers();}6. 具体主题订单主题importjava.util.ArrayList;importjava.util.List;/** * 订单主题状态变化时通知所有人 */publicclassOrderSubjectimplementsSubject{privateListObserverobserverListnewArrayList();privateStringorderStatus;// 状态变更publicvoidsetOrderStatus(StringorderStatus){this.orderStatusorderStatus;// 状态变了 → 通知观察者notifyObservers();}Overridepublicvoidattach(Observerobserver){observerList.add(observer);}Overridepublicvoiddetach(Observerobserver){observerList.remove(observer);}OverridepublicvoidnotifyObservers(){for(Observerobserver:observerList){observer.update(orderStatus);}}}7. 客户端测试publicclassClient{publicstaticvoidmain(String[]args){// 1. 创建主题订单OrderSubjectorderSubjectnewOrderSubject();// 2. 创建观察者UserObserveruserObservernewUserObserver();LogisticsObserverlogisticsObservernewLogisticsObserver();StockObserverstockObservernewStockObserver();// 3. 注册订阅orderSubject.attach(userObserver);orderSubject.attach(logisticsObserver);orderSubject.attach(stockObserver);// 4. 改变订单状态 → 自动通知System.out.println( 订单状态变为已支付 );orderSubject.setOrderStatus(已支付);}}8. 运行结果 订单状态变为已支付 【用户通知】订单状态更新已支付已推送APP消息 【物流系统】准备打包发货 【库存系统】确认扣减库存完成四、Java 内置观察者了解Java 提供原生支持被观察者java.util.Observable类观察者java.util.Observer接口缺点Observable 是类不是接口无法多继承线程不安全功能简单实际开发一般自己实现或使用 Guava、Spring 事件。五、观察者模式优缺点优点松耦合发布者与订阅者互不依赖可独立扩展动态灵活可随时增删观察者符合开闭原则新增观察者无需修改主题广播机制一次状态变更多方同步缺点观察者过多时通知效率下降循环依赖可能导致死循环观察者只知道主题变化不知道如何变化调试链路较长六、经典框架应用面试高频1. Spring Event 事件机制ApplicationEvent事件ApplicationListener观察者ApplicationContext发布者2. RabbitMQ / Kafka / RocketMQ消息队列是异步化、分布式版的观察者模式。3. GUI 事件监听按钮点击事件onClickListener是典型观察者。4. MyBatis 插件机制底层使用观察者思想实现拦截与增强。5. ZooKeeper Watch 机制节点变化自动通知客户端。七、观察者模式 VS 责任链模式面试对比对比项观察者模式责任链模式结构一对多一对一链式通知方式广播给所有人依次传递直到被处理耦合低中等目的同步状态、广播通知分级处理、权限过滤八、总结观察者模式 发布 订阅核心一对多、状态自动通知、松耦合被观察者只负责通知不关心观察者逻辑适合事件驱动、状态同步、消息广播场景是 Spring、消息队列、事件驱动架构的核心思想一句话记忆一个主题多监听状态一变全通知解耦发布与订阅事件驱动最常用