当前位置: 首页 > news >正文

观察者模式与相关模式的对比

概要

简单说,观察者模式就是“一喊多应”的机制——一个对象(发布者)状态变了,所有依赖它的对象(订阅者)自动收到通知并更新自己。

想象一个微信群:你发了一条消息“今晚聚餐”,群里所有人(订阅者)都收到了通知,每个人可以决定怎么回复(更新自己的状态)。发消息的人不需要知道谁在群里,也不需要挨个私聊——这就是观察者模式的核心思想:发布者和订阅者解耦

但软件设计里不止这一种“一喊多应”的模式。还有发布-订阅模式、中介者模式、责任链模式……它们看起来很像,但解决的是不同的问题。就像“喊人吃饭”和“喊人开会”虽然都是喊,但流程、目的、参与者都不一样。


整体架构流程

观察者模式的“舞台”

观察者模式有三个角色:

  1. 主题(Subject):被观察的对象,比如“天气站”。它维护一个订阅者列表,状态变化时挨个通知。
  2. 观察者(Observer):订阅者,比如“手机天气App”。它注册到主题上,收到通知后更新自己。
  3. 客户端(Client):负责把观察者注册到主题上,或者取消注册。

流程
客户端把观察者注册到主题 → 主题状态变化 → 主题遍历所有观察者,调用它们的更新方法 → 每个观察者按自己的逻辑响应。

相关模式的“变种舞台”

我们对比三个最常混淆的模式:

模式核心比喻关键区别
观察者模式微信群@所有人发布者直接通知订阅者,订阅者之间不知道彼此
发布-订阅模式微信公众号发布者和订阅者之间有个“消息中心”做中间人
中介者模式房产中介所有对象通过一个中介通信,避免对象之间直接耦合
责任链模式公司审批流程请求沿着链条传递,直到有人处理

技术名词解释

1. 观察者模式(Observer Pattern)

定义:定义对象之间一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都得到通知并自动更新。

生活类比:你订阅了一个YouTube频道(主题),频道更新时(状态变化),你(观察者)会收到推送通知。频道主不知道你是谁,你也不需要知道频道主怎么运营。

关键点

  • 直接通知:主题直接调用观察者的方法,没有中间人
  • 同步(挨个通知):默认是同步的——主题通知观察者A,A处理完,再通知B,B处理完……就像老师点名,一个一个来
  • 观察者知道主题:观察者需要持有主题的引用,才能注册和接收通知

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 { List<Observer> observers; void notifyObservers() { for (Observer o : observers) { o.update(price); // 直接调用,同步 } } } // 发布-订阅模式:通过消息代理 class MessageBroker { Map<String, List<Subscriber>> 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); // 传给下一个 } } }

小结

观察者模式是“一喊多应”的起点,但它有局限性:同步通知、发布者知道订阅者。当系统变大、需要解耦时,就演化出了发布-订阅模式(加中间人)、中介者模式(集中控制)、责任链模式(链式处理)。

记住这个类比

  • 观察者模式 = 微信群@所有人(直接喊)
  • 发布-订阅模式 = 微信公众号(通过平台推送)
  • 中介者模式 = 房产中介(统一协调)
  • 责任链模式 = 公司审批流程(逐级传递)

一句话总结
如果只是“通知”就够了,用观察者;如果需要“解耦+异步”,用发布-订阅;如果需要“控制交互逻辑”,用中介者;如果需要“灵活处理链”,用责任链。

最后提醒:设计模式不是“哪个更好”,而是“哪个更合适”。就像工具箱里的螺丝刀和扳手——拧螺丝用螺丝刀,拧螺母用扳手,选对了工具,活就干得漂亮。

http://www.jsqmd.com/news/998264/

相关文章:

  • 专业5G仿真平台UERANSIM:构建完整5G网络测试环境的开源解决方案
  • AI新周期下派欧云二次冲击港交所,边缘计算市场谁能拔得头筹?
  • 抖音直播数据采集实战:解锁实时用户行为分析的完整方案
  • 卫生间漏水到楼下怎么查找漏水点?2026石河子24小时上门维修电话TOP7机构推荐,免费勘察+精准定位,专业师傅处理屋顶墙体洗手间暗管漏水 - 一修哥咨询
  • Hermes Agent 子任务委派机制深度剖析:delegate_task 的设计与实现
  • 2026 淄博防水补漏公司 TOP5 口碑榜:漏水检测、地下室外墙漏水、飘窗渗水修缮、瓷砖修补翻新行业资讯 - 泛家庭维修
  • 口袋妖怪存档管理神器PKSM:从初代到第八代的完整解决方案
  • 第二十二篇 从随机过程到IMU噪声模型
  • 大语言模型提示压缩技术:块状因果掩码原理与实践
  • 北京黄金铂金K金钻石回收哪家靠谱?五家正规门店实力对比与避坑指南 - 资讯速览
  • 2026年上海网约车租赁市场深度横评:合规双证与新能源化选购指南 - 优质企业观察收录
  • 3种高效方法解决NCM加密音乐格式转换,实现跨平台播放自由
  • 渐进分析与拉普拉斯-贝尔特拉米算子在多视图数据中的应用
  • 闲置黄金怎么卖最划算 2026深圳正规回收店推荐 - 余生黄金回收
  • 2026 辽源卫生间漏水不用砸砖?微创补漏靠谱方案 - 苏易修缮
  • 2026山东聊城青少年叛逆教育学校地址汇总!全封闭管教,这几家正规机构家长放心选 - 小途xt
  • 基于大模型的运维 SOP 自动生成与执行:从经验文档到可执行脚本,运维知识的工程化
  • 遗传算法工程化实战:从教科书到工业级稳定收敛
  • 跨越次元壁:MMD Tools如何让Blender与初音未来完美相遇
  • 2026 年合肥肥西防水补漏怎么选?肥西速易修防水甄别挑选指南 - 资讯速览
  • 2026 武汉 5 大青少年矫正学校榜单|专治叛逆网瘾早恋厌学,央视背书机构领跑 - 辛云教育资讯
  • 南京建邺区金价高位,上门回收黄金巧变现 - 上门黄金回收
  • Verilog仿真调试:别再只会用$display了,$monitor、$strobe和$write的区别与实战场景
  • 别让命名毁了你的流片:Innovus中update_names/changeInstName的隐藏技巧与避坑指南
  • PowerPC 604e微架构解析:超标量、乱序执行与缓存一致性设计
  • 出黄金必看!长沙正规回收门店汇总 - 逸程
  • 2026青岛迪奥名包回收靠谱商家排名 闲置奢包高价焕新首选 - 名奢变现站
  • 逆向分析实战:用CE和OD一步步找到《魔域》老端魔石商店的购买Call与物品遍历公式
  • 深度解析:精油代工 核心工艺与合规生产实践 - 资讯快报
  • MPC8540接口电气特性深度解析:从参数到PCB设计的硬件稳定性基石