Python 中的 Observer(观察者)设计模式 是一种行为型设计模式,用于定义一种订阅机制,让多个观察者对象在某一对象的状态发生变化时自动接收到通知。该模式常用于事件驱动的架构,例如 GUI 系统、消息推送系统等。
Observer 模式的组成
-
Subject(被观察者):
- 持有观察者列表,并提供添加、移除观察者的方法。
- 当状态变化时,通知所有观察者。
-
Observer(观察者):
- 定义接口,接收来自 Subject 的更新。
-
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 的 weakref
和 Observable
可用于更高级的实现,例如通过 abc
模块定义接口或利用事件机制。
使用 Observer Pattern
的替代方案
asyncio
:实现异步事件通知。pubsub
(发布订阅库) :如PyPubSub
。- GUI 框架自带的信号与槽:例如 PyQt。
适用场景
- 事件驱动系统:按钮点击事件、输入框监听。
- 实时通知系统:新闻订阅、股票更新。
- 解耦系统模块:通过观察者减少模块间的直接依赖。
总结
Observer 模式在 Python 中实现起来非常自然,且可以根据实际需求选择基本实现或利用更高级的特性(如弱引用、生成器等)优化。