news 2026/6/25 12:24:33

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/6/23 11:07:54

从安全小白到macOS防火墙贡献者:我的LuLu开源成长之路

从安全小白到macOS防火墙贡献者:我的LuLu开源成长之路 【免费下载链接】LuLu LuLu is the free macOS firewall 项目地址: https://gitcode.com/gh_mirrors/lu/LuLu 还记得第一次发现电脑莫名其妙联网时的恐慌吗?那种感觉就像家里进了陌生人&…

作者头像 李华
网站建设 2026/6/24 19:53:04

餐饮行业数字化工具应用指南:从传统经营到智能升级

餐饮行业数字化工具应用指南:从传统经营到智能升级 【免费下载链接】bee 微信小程序-餐饮点餐外卖-开箱即用 项目地址: https://gitcode.com/GitHub_Trending/be/bee 引言:数字化浪潮下的餐饮变革 "每天高峰期,我们的服务员要同…

作者头像 李华
网站建设 2026/6/23 18:05:24

2、生成对抗网络(GANs)入门与实战解析

生成对抗网络(GANs)入门与实战解析 1. 引言 机器能否思考这一问题的历史比计算机本身还要悠久。1950 年,著名数学家、逻辑学家和计算机科学家艾伦图灵在论文《计算机器与智能》中提出了图灵测试。在这个测试中,一名不知情的观察者与门后的两个人进行交流,一个是人类,另…

作者头像 李华
网站建设 2026/6/15 17:22:19

如何快速掌握PC微信小程序wxapkg解密:2025终极完整教程

如何快速掌握PC微信小程序wxapkg解密:2025终极完整教程 【免费下载链接】pc_wxapkg_decrypt_python PC微信小程序 wxapkg 解密 项目地址: https://gitcode.com/gh_mirrors/pc/pc_wxapkg_decrypt_python 想要深入了解PC微信小程序解密技术?本指南将…

作者头像 李华
网站建设 2026/6/16 16:29:10

Python 读取 txt 某几列绘图的完整方法

Python 读取 txt 文件指定列并绘图的核心流程是:读取 txt 数据→提取目标列→数据预处理→绘图可视化。本文基于pandas(高效读取 / 处理数据)和matplotlib(绘图核心库),覆盖不同 txt 格式(有无表…

作者头像 李华