📋 Research Summary
观察者模式是事件驱动架构的基础。从 React 的状态更新、Vue 的响应式系统、到消息队列(Kafka、RabbitMQ),都是其变体。它定义了对象间的一对多依赖,当一个对象状态改变时,所有依赖者自动收到通知。
🌱 逻辑原点
如果股票价格变动时需要同时更新行情面板、交易记录、风险监控系统、用户通知,你是让股票挨个调用这些系统,还是让这些系统自己"订阅"股票变动?
状态变化传播与系统可扩展性的矛盾:数据变化需要通知多个地方,但数据源不应该知道所有接收者是谁。

🧠 苏格拉底式对话
1️⃣ 现状:最原始的解法是什么?
让数据源直接调用所有需要通知的对象:
python
class Stock:
def __init__(self):
self._price = 0
self._dashboard = Dashboard()
self._logger = Logger()
self._risk_system = RiskSystem()
def set_price(self, price):
self._price = price
# 直接调用所有接收者
self._dashboard.update(price)
self._logger.log(price)
self._risk_system.check(price)
优点 :直接,流程清晰。
问题:数据源与所有接收者紧耦合,新增接收者需要修改数据源。
2️⃣ 瓶颈:规模扩大 100 倍时会在哪里崩溃?
当系统有 100 个不同的组件需要监听价格变动时:
- 耦合爆炸:数据源需要引用 100 个接收者
- 修改困难:新增一个接收者,数据源代码需要修改
- 违反开闭原则:扩展功能需要修改已有代码
- 性能问题:某些接收者处理慢,阻塞价格更新
- 循环依赖风险:A 监听 B,B 又监听 A
核心矛盾:数据源不应该知道谁在监听,接收者应该能动态订阅和取消订阅。
3️⃣ 突破:必须引入什么新维度?
订阅-发布机制。
不是"数据源主动调用接收者",而是"接收者订阅数据源,数据源只负责广播"。数据源维护一个订阅者列表,状态变化时遍历通知:
Dashboard --订阅--> Stock <--订阅-- Logger
|
v
价格变化时广播给所有订阅者
这就是观察者的本质:将"推"模式转变为"拉-推"模式,实现发布者与订阅者的解耦。
📊 视觉骨架
维护 maintain
订阅 subscribe
订阅 subscribe
通知 notify
通知 notify
主题 Subject
订阅者列表 Observer List
观察者A Observer A
观察者B Observer B
关键洞察:观察者模式让主题只依赖抽象的观察者接口,不依赖具体观察者。观察者可以动态订阅/取消订阅,主题完全不知道也不关心谁在监听。这实现了真正的解耦。
⚖️ 权衡模型
公式:
Observer = 解决了状态变化的广播通知 + 牺牲了执行顺序确定性 + 增加了循环通知风险
代价分析:
- ✅ 解决: 发布者与订阅者解耦、支持动态订阅、符合开闭原则、支持一对多通信
- ❌ 牺牲: 执行顺序不确定、通知可能丢失(如果订阅者未及时处理)、调试困难
- ⚠️ 增加: 循环通知风险、内存泄漏风险(忘记取消订阅)、订阅者执行时间影响发布者
使用建议:当一个对象的改变需要同时改变其他对象,且不知道具体有多少对象需要改变时使用。典型场景:事件系统、消息队列、MVC 中的模型-视图更新、响应式编程。
🔁 记忆锚点
python
class Subject:
"""
观察者的本质:订阅-发布机制
"""
def __init__(self):
self._observers: List[Observer] = []
def attach(self, observer: "Observer") -> None:
"""订阅"""
self._observers.append(observer)
def detach(self, observer: "Observer") -> None:
"""取消订阅"""
self._observers.remove(observer)
def notify(self) -> None:
"""广播通知所有订阅者"""
for observer in self._observers:
observer.update(self)
class Stock(Subject):
"""具体主题:股票"""
def __init__(self):
super().__init__()
self._price = 0
@property
def price(self) -> float:
return self._price
@price.setter
def price(self, value: float) -> None:
self._price = value
self.notify() # 状态变化时自动通知
# 观察者:只需要实现 update 方法
class Dashboard(Observer):
def update(self, subject: Subject) -> None:
if isinstance(subject, Stock):
print(f"Dashboard updated: {subject.price}")
一句话本质: 观察者模式 = 订阅-发布机制,实现状态变化的自动广播。