在 Python 中实现观察者模式可以遵循以下具体步骤,这些步骤清晰地划分了角色和交互流程:
步骤 1:定义主题(Subject)基类
主题是被观察的对象,负责管理观察者和发送通知。需实现以下核心方法:
- 存储观察者的容器(如列表)
- 添加观察者的方法(
attach
) - 移除观察者的方法(
detach
) - 通知所有观察者的方法(
notify
)
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):
"""从列表中移除观察者"""
try:
self._observers.remove(observer)
except ValueError:
pass # 忽略未找到的观察者
def notify(self, *args, **kwargs):
"""通知所有观察者状态变化"""
for observer in self._observers:
observer.update(*args, **kwargs) # 调用观察者的更新方法
步骤 2:实现具体主题(ConcreteSubject)
具体主题是实际业务对象,维护自身状态,当状态变化时触发通知。
class WeatherStation(Subject): # 继承主题基类
def __init__(self):
super().__init__()
self._temperature = None # 示例:温度状态
@property
def temperature(self):
return self._temperature
@temperature.setter
def temperature(self, new_temp):
self._temperature = new_temp # 更新状态
self.notify(new_temp) # 状态变化时通知观察者
步骤 3:定义观察者(Observer)基类/接口
观察者是接收通知的对象,需定义一个更新方法(update
),供主题调用。
class Observer:
def update(self, *args, **kwargs):
"""接收主题通知的方法,子类必须实现"""
raise NotImplementedError("子类必须重写 update 方法")
步骤 4:实现具体观察者(ConcreteObserver)
具体观察者根据自身需求实现update
方法,处理主题发送的通知。
class PhoneDisplay(Observer): # 手机显示屏观察者
def update(self, temp):
print(f"手机显示:当前温度 {temp}°C")
class WindowDisplay(Observer): # 窗口显示屏观察者
def update(self, temp):
print(f"窗口显示:温度更新为 {temp}°C")
步骤 5:使用观察者模式
创建主题和观察者实例,关联它们,并触发状态变化验证效果。
# 1. 创建主题(被观察者)
weather_station = WeatherStation()
# 2. 创建观察者
phone_display = PhoneDisplay()
window_display = WindowDisplay()
# 3. 注册观察者到主题
weather_station.attach(phone_display)
weather_station.attach(window_display)
# 4. 改变主题状态(自动通知观察者)
print("--- 温度变为 25°C ---")
weather_station.temperature = 25
print("\n--- 温度变为 30°C ---")
weather_station.temperature = 30
# 5. 移除一个观察者
weather_station.detach(phone_display)
print("\n--- 移除手机显示后,温度变为 28°C ---")
weather_station.temperature = 28
执行结果
--- 温度变为 25°C ---
手机显示:当前温度 25°C
窗口显示:温度更新为 25°C
--- 温度变为 30°C ---
手机显示:当前温度 30°C
窗口显示:温度更新为 30°C
--- 移除手机显示后,温度变为 28°C ---
窗口显示:温度更新为 28°C
核心逻辑总结
- 主题与观察者解耦:主题只需知道观察者有
update
方法,无需了解其具体实现;观察者也无需知道主题的内部逻辑。 - 动态关联:通过
attach
和detach
可以随时添加/移除观察者,灵活性高。 - 自动通知:主题状态变化时,主动调用所有注册观察者的
update
方法,实现"一处变化,多处响应"。
这种模式适用于事件监听、状态同步、发布-订阅系统等场景,例如 GUI 中的按钮点击事件、数据更新通知等。