概要简单说观察者模式就是“一喊多应”的机制——一个对象发布者状态变了所有依赖它的对象订阅者自动收到通知并更新自己。想象一个微信群你发了一条消息“今晚聚餐”群里所有人订阅者都收到了通知每个人可以决定怎么回复更新自己的状态。发消息的人不需要知道谁在群里也不需要挨个私聊——这就是观察者模式的核心思想发布者和订阅者解耦。但软件设计里不止这一种“一喊多应”的模式。还有发布-订阅模式、中介者模式、责任链模式……它们看起来很像但解决的是不同的问题。就像“喊人吃饭”和“喊人开会”虽然都是喊但流程、目的、参与者都不一样。整体架构流程观察者模式的“舞台”观察者模式有三个角色主题Subject被观察的对象比如“天气站”。它维护一个订阅者列表状态变化时挨个通知。观察者Observer订阅者比如“手机天气App”。它注册到主题上收到通知后更新自己。客户端Client负责把观察者注册到主题上或者取消注册。流程客户端把观察者注册到主题 → 主题状态变化 → 主题遍历所有观察者调用它们的更新方法 → 每个观察者按自己的逻辑响应。相关模式的“变种舞台”我们对比三个最常混淆的模式模式核心比喻关键区别观察者模式微信群所有人发布者直接通知订阅者订阅者之间不知道彼此发布-订阅模式微信公众号发布者和订阅者之间有个“消息中心”做中间人中介者模式房产中介所有对象通过一个中介通信避免对象之间直接耦合责任链模式公司审批流程请求沿着链条传递直到有人处理技术名词解释1. 观察者模式Observer Pattern定义定义对象之间一对多的依赖关系当一个对象状态改变时所有依赖它的对象都得到通知并自动更新。生活类比你订阅了一个YouTube频道主题频道更新时状态变化你观察者会收到推送通知。频道主不知道你是谁你也不需要知道频道主怎么运营。关键点直接通知主题直接调用观察者的方法没有中间人同步挨个通知默认是同步的——主题通知观察者AA处理完再通知BB处理完……就像老师点名一个一个来观察者知道主题观察者需要持有主题的引用才能注册和接收通知2. 发布-订阅模式Publish-Subscribe Pattern定义发布者和订阅者通过一个消息代理中间件通信发布者发送消息到特定频道订阅者从频道接收消息。生活类比你订阅了“科技新闻”这个微信公众号频道。公众号作者发布者把文章发到微信平台消息代理微信平台再推送给所有订阅者。发布者不知道谁订阅了订阅者也不知道谁发布了。关键点间接通信发布者和订阅者完全解耦通过消息代理通信异步非实时发布者发完消息就走订阅者可以稍后处理比如微信消息可以延迟接收支持多对多一个发布者可以发到多个频道一个订阅者可以订阅多个频道3. 中介者模式Mediator Pattern定义用一个中介对象来封装一组对象之间的交互使对象之间不需要显式相互引用。生活类比租房时你租客和房东不直接联系而是通过中介中介者沟通。中介负责传递信息、协调时间、处理纠纷。你和房东之间没有直接耦合。关键点集中控制所有通信都经过中介中介可以控制交互逻辑减少多对多原本N个对象互相通信N²条连接变成每个对象只和中介通信N条连接中介知道所有对象中介持有所有参与者的引用可以协调它们的行为4. 责任链模式Chain of Responsibility Pattern定义将请求的发送者和接收者解耦使多个接收者都有机会处理请求将这些接收者连成一条链沿着链传递请求直到被处理。生活类比你提交请假申请请求先到组长处理者1组长批不了权限不够→ 传到经理处理者2经理批了处理成功。每个处理者要么处理要么传给下一个。关键点链式传递请求沿着链单向传递直到被处理每个处理者独立每个处理者只知道自己下一个是谁不知道链的全貌处理者可以决定是否处理可以处理并停止传递也可以只处理一部分再继续传技术细节场景对比用“通知系统”看区别假设你要设计一个“股票价格变动通知系统”场景A用观察者模式股票价格类主题维护一个“订阅者列表”比如手机App、大屏幕、邮件服务价格变化时主题直接调用每个订阅者的update(price)方法问题如果订阅者很多比如10万个主题要挨个通知可能阻塞卡住。而且主题需要知道所有订阅者的接口方法签名场景B用发布-订阅模式股票价格类发布者把价格变化消息发到“股票频道”消息队列手机App、大屏幕、邮件服务订阅者各自从频道拉取消息好处发布者不需要知道谁订阅了订阅者可以异步处理比如手机App收到消息后慢慢更新UI不影响价格更新典型实现Redis的发布订阅、RabbitMQ消息队列场景C用中介者模式股票价格类、手机App、大屏幕、邮件服务都注册到一个“系统中介者”价格变化时价格类通知中介者中介者决定怎么通知其他组件比如先通知大屏幕再通知手机App最后发邮件好处中介者可以控制通知顺序、过滤重复通知、做日志记录典型实现MVC中的Controller控制器就是中介者View视图和Model模型不直接通信场景D用责任链模式股票价格变化时请求先到“价格过滤器”比如只处理涨幅超过5%的过滤器处理不了涨幅不够→ 传给“告警处理器”触发告警告警处理器处理完→ 传给“日志记录器”记录到数据库好处每个处理器只负责一件事可以灵活组合比如可以调整过滤器的顺序选择指南什么时候用哪个需求推荐模式理由一个对象变化多个对象需要更新且更新逻辑简单观察者模式实现简单直接通知发布者和订阅者完全解耦需要异步处理发布-订阅模式消息代理解耦支持高并发多个对象之间的交互逻辑复杂需要集中控制中介者模式中介者统一管理交互逻辑请求需要经过多个处理步骤每个步骤独立责任链模式灵活组合处理链容易扩展代码级对比伪代码示意// 观察者模式主题直接通知 class StockPrice { ListObserver observers; void notifyObservers() { for (Observer o : observers) { o.update(price); // 直接调用同步 } } } // 发布-订阅模式通过消息代理 class MessageBroker { MapString, ListSubscriber channels; void publish(String channel, Message msg) { for (Subscriber s : channels.get(channel)) { s.receive(msg); // 可以是异步的 } } } // 中介者模式通过中介通信 class Mediator { void notify(Component sender, Event event) { if (event priceChange) { display.update(event); // 中介决定顺序 email.send(event); } } } // 责任链模式链式传递 abstract class Handler { Handler next; void handle(Request req) { if (canHandle(req)) { process(req); } else if (next ! null) { next.handle(req); // 传给下一个 } } }小结观察者模式是“一喊多应”的起点但它有局限性同步通知、发布者知道订阅者。当系统变大、需要解耦时就演化出了发布-订阅模式加中间人、中介者模式集中控制、责任链模式链式处理。记住这个类比观察者模式 微信群所有人直接喊发布-订阅模式 微信公众号通过平台推送中介者模式 房产中介统一协调责任链模式 公司审批流程逐级传递一句话总结如果只是“通知”就够了用观察者如果需要“解耦异步”用发布-订阅如果需要“控制交互逻辑”用中介者如果需要“灵活处理链”用责任链。最后提醒设计模式不是“哪个更好”而是“哪个更合适”。就像工具箱里的螺丝刀和扳手——拧螺丝用螺丝刀拧螺母用扳手选对了工具活就干得漂亮。