Python设计模式详解之16 —— 观察者模式

Python 中的 Observer(观察者)设计模式 是一种行为型设计模式,用于定义一种订阅机制,让多个观察者对象在某一对象的状态发生变化时自动接收到通知。该模式常用于事件驱动的架构,例如 GUI 系统、消息推送系统等。


Observer 模式的组成

  1. Subject(被观察者)

    • 持有观察者列表,并提供添加、移除观察者的方法。
    • 当状态变化时,通知所有观察者。
  2. Observer(观察者)

    • 定义接口,接收来自 Subject 的更新。
  3. ConcreteSubject 和 ConcreteObserver

    • ConcreteSubject 负责存储具体的状态并通知观察者。
    • ConcreteObserver 实现观察者接口,响应状态变化。

如何在 Python 中实现 Observer 模式

示例:股票价格通知系统
python 复制代码
# 观察者接口
class Observer:
    def update(self, subject):
        raise NotImplementedError("Subclasses must implement this method.")

# 被观察者基类
class Subject:
    def __init__(self):
        self._observers = []  # 存储观察者

    def attach(self, observer):
        if observer not in self._observers:
            self._observers.append(observer)

    def detach(self, observer):
        self._observers.remove(observer)

    def notify(self):
        for observer in self._observers:
            observer.update(self)

# 具体的被观察者
class Stock(Subject):
    def __init__(self, name, price):
        super().__init__()
        self.name = name
        self._price = price

    @property
    def price(self):
        return self._price

    @price.setter
    def price(self, new_price):
        if self._price != new_price:
            self._price = new_price
            self.notify()  # 通知观察者价格已变化

# 具体的观察者
class Investor(Observer):
    def __init__(self, name):
        self.name = name

    def update(self, subject):
        print(f"通知 {self.name}: {subject.name} 的价格已更新为 {subject.price}.")

# 使用 Observer 模式
if __name__ == "__main__":
    # 创建股票对象
    google_stock = Stock("Google", 1500)

    # 创建投资者对象
    investor_a = Investor("Alice")
    investor_b = Investor("Bob")

    # 添加观察者
    google_stock.attach(investor_a)
    google_stock.attach(investor_b)

    # 修改价格并触发通知
    google_stock.price = 1550
    google_stock.price = 1600

    # 移除观察者
    google_stock.detach(investor_a)
    google_stock.price = 1650
输出结果:
复制代码
通知 Alice: Google 的价格已更新为 1550.
通知 Bob: Google 的价格已更新为 1550.
通知 Alice: Google 的价格已更新为 1600.
通知 Bob: Google 的价格已更新为 1600.
通知 Bob: Google 的价格已更新为 1650.

使用 Python 内置的 weakref.WeakSet 优化

weakref.WeakSet 可以防止因为观察者未被移除而导致的内存泄漏:

python 复制代码
from weakref import WeakSet

class Subject:
    def __init__(self):
        self._observers = WeakSet()

    def attach(self, observer):
        self._observers.add(observer)

    def detach(self, observer):
        self._observers.discard(observer)

    def notify(self):
        for observer in self._observers:
            observer.update(self)

使用 Python 的内置库实现

Python 的 weakrefObservable 可用于更高级的实现,例如通过 abc 模块定义接口或利用事件机制。

使用 Observer Pattern 的替代方案
  • asyncio:实现异步事件通知。
  • pubsub(发布订阅库) :如 PyPubSub
  • GUI 框架自带的信号与槽:例如 PyQt。

适用场景

  1. 事件驱动系统:按钮点击事件、输入框监听。
  2. 实时通知系统:新闻订阅、股票更新。
  3. 解耦系统模块:通过观察者减少模块间的直接依赖。

总结

Observer 模式在 Python 中实现起来非常自然,且可以根据实际需求选择基本实现或利用更高级的特性(如弱引用、生成器等)优化。

相关推荐
web3.08889998 小时前
微店商品详情API实用
python·json·时序数据库
知乎的哥廷根数学学派8 小时前
基于数据驱动的自适应正交小波基优化算法(Python)
开发语言·网络·人工智能·pytorch·python·深度学习·算法
sunfove8 小时前
将 Python 仿真工具部署并嵌入个人博客
开发语言·数据库·python
Learner8 小时前
Python类
开发语言·python
2501_941329729 小时前
门及其组件定位识别_YOLO13-C3k2-PoolingFormer改进模型研究
python
Ancelin安心9 小时前
kali-dirsearch的使用
linux·运维·服务器·python·计算机网络·web安全·网络安全
努力学习的小洋9 小时前
Python训练打卡Day5离散特征的处理-独热编码
人工智能·python·机器学习
Sherry Wangs9 小时前
【ML】机器学习进阶
人工智能·python·机器学习
X1A0RAN10 小时前
python 借助 paramiko 库执行 SSH命令报错:input is not a terminal 解决方式
开发语言·python·ssh
百***787510 小时前
Grok-4.1与GPT-5.2深度对比:技术差异、适用场景及Python集成指南
java·python·gpt