news 2026/4/15 21:40:46

Python 观察者模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 观察者模式

Python 中的观察者模式(Observer Pattern)

观察者模式是一种行为型设计模式,其核心目的是:
定义对象间的一种一对多依赖关系,当一个对象(主题/被观察者)的状态发生改变时,所有依赖它的对象(观察者)都得到通知并自动更新

形象比喻:就像订阅报纸——你(观察者)订阅了报纸(主题),每当有新报纸出版,邮递员就会自动送到你家。

观察者模式的优点
  • 实现主题和观察者之间的松耦合(主题只知道观察者列表,不关心具体类型)
  • 支持广播通信(一个变化通知多个对象)
  • 符合“开闭原则”:新增观察者无需修改主题代码
典型应用场景
  • GUI 系统:按钮点击通知多个监听器
  • 事件驱动编程(如 tkinter、PyQt 的信号槽)
  • 发布-订阅系统(消息队列、事件总线)
  • 数据变更通知(如股票价格更新、天气预报)
  • MVC 架构中的 View 更新
Python 实现示例:股票价格监控
fromabcimportABC,abstractmethodfromtypingimportList# 观察者接口(Observer)classObserver(ABC):@abstractmethoddefupdate(self,subject):pass# 具体观察者:图表显示classChartDisplay(Observer):defupdate(self,subject):print(f"【图表】股票价格更新:{subject.stock_name}= ${subject.price:.2f}")# 具体观察者:短信通知classSMSAlert(Observer):def__init__(self,phone_number:str):self.phone_number=phone_numberdefupdate(self,subject):ifsubject.price>150:# 价格超过150时才发短信print(f"【短信】发送到{self.phone_number}{subject.stock_name}已突破 ${subject.price:.2f}!")# 具体观察者:邮件通知classEmailAlert(Observer):def__init__(self,email:str):self.email=emaildefupdate(self,subject):print(f"【邮件】发送到{self.email}{subject.stock_name}最新价格 ${subject.price:.2f}")# 主题(Subject / Observable)classStock:def__init__(self,name:str,price:float):self.stock_name=name self.price=price self._observers:List[Observer]=[]defattach(self,observer:Observer):ifobservernotinself._observers:self._observers.append(observer)print(f"{observer.__class__.__name__}已订阅{self.stock_name}")defdetach(self,observer:Observer):ifobserverinself._observers:self._observers.remove(observer)print(f"{observer.__class__.__name__}已取消订阅{self.stock_name}")defnotify(self):print(f"通知所有观察者...")forobserverinself._observers:observer.update(self)defset_price(self,new_price:float):ifnew_price!=self.price:self.price=new_priceprint(f"{self.stock_name}价格变动 → ${new_price:.2f}")self.notify()# 客户端使用if__name__=="__main__":# 创建股票(主题)apple_stock=Stock("AAPL",145.0)# 创建观察者chart=ChartDisplay()sms=SMSAlert("138-1234-5678")email=EmailAlert("investor@example.com")# 订阅apple_stock.attach(chart)apple_stock.attach(sms)apple_stock.attach(email)print("\n--- 第一次价格更新 ---")apple_stock.set_price(152.0)# 触发通知print("\n--- 第二次价格更新 ---")apple_stock.set_price(148.0)# 短信不触发(未超150)print("\n--- 取消短信订阅 ---")apple_stock.detach(sms)print("\n--- 第三次价格更新 ---")apple_stock.set_price(160.0)# 只有图表和邮件收到通知

输出

ChartDisplay 已订阅 AAPL SMSAlert 已订阅 AAPL EmailAlert 已订阅 AAPL --- 第一次价格更新 --- AAPL 价格变动 → $152.00 通知所有观察者... 【图表】股票价格更新:AAPL = $152.00 【短信】发送到 138-1234-5678:AAPL 已突破 $152.00! 【邮件】发送到 investor@example.com:AAPL 最新价格 $152.00 --- 第二次价格更新 --- AAPL 价格变动 → $148.00 通知所有观察者... 【图表】股票价格更新:AAPL = $148.00 【邮件】发送到 investor@example.com:AAPL 最新价格 $148.00 --- 取消短信订阅 --- SMSAlert 已取消订阅 AAPL --- 第三次价格更新 --- AAPL 价格变动 → $160.00 通知所有观察者... 【图表】股票价格更新:AAPL = $160.00 【邮件】发送到 investor@example.com:AAPL 最新价格 $160.00
Pythonic 更简洁实现:使用属性装饰器

Python 中可以用@property实现自动通知:

classObservable:def__init__(self):self._observers=[]defattach(self,observer):self._observers.append(observer)defdetach(self,observer):self._observers.remove(observer)defnotify(self):forobserverinself._observers:observer(self)# 直接传整个对象classStock(Observable):def__init__(self,name,price):super().__init__()self._name=name self._price=price@propertydefprice(self):returnself._price@price.setterdefprice(self,value):self._price=value self.notify()# 自动通知# 使用stock=Stock("TSLA",800)stock.attach(lambdas:print(f"价格更新:{s._name}= ${s._price}"))stock.price=850# 自动触发
内置支持:事件库

Python 标准库没有内置观察者,但第三方库很成熟:

  • blinker:轻量级信号系统
  • PyDispatcher:经典事件分发
  • GUI 框架(如tkinterPyQtPySide)自带信号槽机制
观察者模式结构总结
角色说明
Subject主题,维护观察者列表,提供 attach/detach/notify
Observer抽象观察者,定义 update 接口
ConcreteSubject具体主题(如 Stock),状态变化时调用 notify
ConcreteObserver具体观察者(如 ChartDisplay、SMSAlert)
观察者模式 vs 发布-订阅模式
  • 观察者模式:主题直接持有观察者引用(紧耦合于同一进程)
  • 发布-订阅(Pub/Sub):通过消息中间件解耦(支持分布式,如 Redis、Kafka)
Python 中的实用建议
  • 小型项目:手写观察者(如上例)
  • 中型项目:使用@property+ 回调列表
  • GUI/事件驱动:直接用框架的信号机制
  • 大型/分布式:使用消息队列(Celery、RabbitMQ)
注意事项
  • 通知顺序不确定(除非显式排序)
  • 避免在 update 中修改主题状态(可能无限循环)
  • 多线程时需加锁保护观察者列表
  • 取消订阅很重要(避免内存泄漏)

观察者模式是事件驱动编程的核心,在 Python 的 GUI、Web 框架、异步系统中无处不在。

如果你想看更高级的例子(如多线程安全观察者、结合 asyncio 的异步通知、使用 blinker 库的信号系统),或者与其他模式结合(如观察者 + 策略),随时告诉我!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/10 22:25:19

STLink驱动安装蓝屏?全面讲解解决方案

STLink驱动一插就蓝屏?别慌,这份硬核排错指南帮你彻底解决 你有没有遇到过这样的场景:兴冲冲地打开电脑准备调试STM32项目,刚把STLink调试器插上USB口,系统重启后直接“蓝了”——熟悉的白字蓝底界面弹出,…

作者头像 李华
网站建设 2026/4/13 7:56:10

Unstructured API终极指南:5步实现文档智能解析与数据提取

在数字化办公环境中,企业面临的最大挑战之一是如何高效处理海量多格式文档。传统方法需要人工逐一打开不同格式的文件,手动提取关键信息,不仅效率低下,还容易出错。Unstructured API正是为解决这一痛点而生,通过智能解…

作者头像 李华
网站建设 2026/4/13 7:06:53

JLink驱动安装无反应?聚焦USB通信层操作指南

JLink驱动安装无反应?别急着重装,先看懂USB通信链路 你有没有遇到过这样的场景: 手握一块崭新的J-Link调试器,项目正等着烧录固件,结果插上电脑——设备管理器里 悄无声息 ;运行J-Link Installer&#…

作者头像 李华
网站建设 2026/4/15 13:35:07

Open-AutoGLM插件究竟有多强?(9大核心功能首次曝光)

第一章:Open-AutoGLM插件究竟有多强? Open-AutoGLM 是一款基于 GLM 大模型生态开发的智能化插件系统,专为提升自动化任务处理能力而设计。它不仅支持自然语言理解与生成,还能深度集成到各类企业级应用中,实现从数据解析…

作者头像 李华
网站建设 2026/4/14 7:03:03

Open-AutoGLM安装卡在第3步?专家级解决方案一次性解决5类常见报错

第一章:Windows平台部署Open-AutoGLM概述在Windows平台上部署Open-AutoGLM为本地大模型应用开发与测试提供了便捷环境。该框架结合了AutoGLM的自动化推理能力与开放架构,支持在资源受限的桌面环境中运行轻量化大语言任务。部署过程依赖Python生态与相关A…

作者头像 李华
网站建设 2026/4/13 16:38:10

BongoCat终极桌面伴侣:快速打造你的专属互动猫咪

BongoCat终极桌面伴侣:快速打造你的专属互动猫咪 【免费下载链接】BongoCat 让呆萌可爱的 Bongo Cat 陪伴你的键盘敲击与鼠标操作,每一次输入都充满趣味与活力! 项目地址: https://gitcode.com/gh_mirrors/bong/BongoCat 厌倦了单调的…

作者头像 李华