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

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象间的一对多依赖关系

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象间的一对多依赖关系:当一个对象(称为“被观察者”或“Subject”)的状态发生改变时,所有依赖于它的对象(称为“观察者”或“Observers”)都会自动收到通知并更新。该模式解耦了被观察者与观察者,支持动态添加/移除观察者,广泛应用于事件驱动系统、GUI框架(如Java Swing、Android LiveData)、消息总线、发布-订阅系统等场景。

典型结构包括:

  • Subject(被观察者):维护观察者列表,提供注册(attach)、注销(detach)和通知(notify)方法;
  • Observer(观察者):定义更新接口(如update()),由具体观察者实现;
  • 具体被观察者(ConcreteSubject)与具体观察者(ConcreteObserver)实现各自逻辑。

优点:松耦合、可扩展性强、支持广播通信;
缺点:可能引发内存泄漏(若未及时注销)、通知顺序不可控、缺乏回调反馈机制(观察者无法向被观察者返回结果)。

fromabcimportABC,abstractmethodfromtypingimportList,AnyclassObserver(ABC):@abstractmethoddefupdate(self,data:Any)->None:passclassSubject(ABC):def__init__(self):self._observers:List[Observer]=[]defattach(self,observer:Observer)->None:ifobservernotinself._observers:self._observers.append(observer)defdetach(self,observer:Observer)->None:ifobserverinself._observers:self._observers.remove(observer)defnotify(self,data:Any)->None:forobserverinself._observers:observer.update(data)# 示例:天气站通知订阅者classWeatherStation(Subject):defset_temperature(self,temp:float)->None:print(f"天气站更新温度:{temp}°C")self.notify(temp)classPhoneDisplay(Observer):defupdate(self,data:float)->None:print(f"[手机端] 收到温度更新:{data}°C")classWebDisplay(Observer):defupdate(self,data:float)->None:print(f"[网页端] 收到温度更新:{data}°C")# 使用示例station=WeatherStation()phone=PhoneDisplay()web=WebDisplay()station.attach(phone)station.attach(web)station.set_temperature(25.6)# 输出两条通知

观察者模式(Observer)与发布-订阅模式(Pub/Sub)本质目标相似(解耦通知方与接收方),但核心区别在于通信耦合度与中介角色的存在与否,因此不属于严格意义上的同一类模式,而是演进关系:Pub/Sub 可视为观察者模式的松耦合变体或扩展。

核心区别对比

维度观察者模式(Observer)发布-订阅模式(Pub/Sub)
耦合方式被观察者(Subject)直接持有并调用观察者(Observer)引用 →存在直接引用耦合发布者(Publisher)与订阅者(Subscriber)均不互相持有引用,全部通过中间消息代理(Event Bus / Message Broker)通信 →完全解耦
注册机制观察者主动向被观察者注册(subject.attach(observer)订阅者向事件总线注册感兴趣的主题(topic),发布者也只面向总线发布,不感知谁订阅
消息传递通知是同步、即时的方法调用(observer.update()通常支持异步、缓冲、持久化、过滤、广播/单播等高级语义;消息可被暂存、重放、路由
生命周期管理被观察者需显式管理观察者列表(增删),易引发内存泄漏(如未detach)总线统一管理订阅关系,更易实现自动清理(如基于弱引用、超时注销)
典型实现Javajava.util.Observable(已弃用)、.NETIObservable<T>、前端EventTarget.addEventListenerRedis Pub/Sub、RabbitMQ、Vue 3 的mitt、RxJS 的Subject(增强版)、Node.js 的events.EventEmitter(轻量级近似)

🔍关键洞察

  • 观察者模式是对象层级的、同步的、内存内的通知机制;
  • Pub/Sub 是系统/服务层级的、常为异步的、可能跨进程/网络的消息范式,引入了中介(Broker)作为第一公民
    → 因此,Pub/Sub 是观察者模式在分布式、高内聚低耦合需求下的抽象升级,而非简单等价替换
# 简化对比示例:同一事件“用户登录成功”# ✅ Observer(紧耦合):user_service.attach(login_logger)# user_service 直接知道 login_loggeruser_service.attach(email_notifier)user_service.notify_login(user)# 同步调用两个对象方法# ✅ Pub/Sub(松耦合):event_bus.publish("user.login",{"user_id":123})# user_service 不知谁监听# login_logger 和 email_notifier 各自向 event_bus 订阅 "user.login"# event_bus 负责分发,二者互不可见

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

相关文章:

  • STM32定时器输入捕获解码NEC红外信号:原理、配置与状态机实现
  • 南通网站优建设:从零基础到行业标杆的实战避坑指南与深度解析
  • NoFences终极指南:完全免费的Windows桌面分区神器
  • 吉大软院计算机网络考试题型全解析:从TCP/IP到子网划分实战
  • 人在异地不随行同意书怎么公证?线上办理全攻略,不跑冤枉路! - 实用干货补给站
  • Linux cancel 命令详解|CUPS 打印任务取消操作完全指南
  • 小白python入门 - 68. 分类入门
  • AI原生编程语言Boundary:从设计思想到工程实践
  • KMS_VL_ALL_AIO终极指南:一键激活Windows和Office的完整解决方案
  • 海南工业园区雨水收集与海绵城市验收避坑指南:4个常见坑+5条硬标准,源头厂家推荐 - geo88
  • 2026乌鲁木齐别墅庭院门楼凉亭设计建造怎么选?实测分享 - LYL仔仔
  • Zabbix下载安装
  • 中山电缆回收透明计价实用指南 - 广东再生资源回收
  • 公司网站建设升上去:从0到1的破局之路与长期主义的价值坚守
  • 免费构建智能笔记同步系统:用Obsidian Git与本地LLM替代官方服务
  • 基于DeepSeek-V4的智能日程管理工具部署与使用指南
  • 滨州拉伸膜的颜色有哪些选择?
  • 雷达与通信信号仿真:从LFM到混合调制的Matlab实践
  • “袖里乾坤大,壶中日月长”:循环队列的空间复用之道
  • Unity 6000下MelonLoader因StreamWriter构造函数崩溃的深度解析与修复方案
  • 广东小区雨水收集|雨水回收利用模块怎么选不踩坑?2026厂家推荐 - geo88
  • 抖音内容批量下载实战指南:5分钟掌握douyin-downloader高效工具
  • 2026 年克拉玛依诚信的L(+)酒石酸供货商哪家**,你以为是普通果酸的玩意儿,竟藏着改善代谢的“隐形buff”?-瀚扬化工 - 行业推荐【认证官】
  • 电子商务网站建设实训总结:从代码小白到项目实战的蜕变之路与深度复盘
  • 终极解密指南:如何一键破解网易云音乐NCM格式,重获音乐自由
  • AI大模型赋能数据治理:小白也能学会的智能数据资产提升秘籍 | 附实战案例
  • VisualCppRedist AIO终极指南:一键解决Windows软件兼容性问题的完整方案
  • OpenClaw Skills:AI Agent技能仓库的架构解析与实践指南
  • 个体工商户网上注销怎么弄?材料清单 + 操作步骤,看完少走弯路! - 慧办好
  • Wolfpack:私有化部署的AI编程智能体控制室实践指南