观察者模式
本课属于 Coddy Python 学习旅程的“面向对象编程”单元。第 47 课,共 64 课。
观察者模式会创建一种一对多关系:当一个对象(主题)的状态发生变化时,它会通知多个对象(观察者)。
这是一个用于管理观察者的简单 Subject 类:
class Subject:
def __init__(self):
self._observers = []
def add_observer(self, observer):
self._observers.append(observer)
def notify(self, message):
for observer in self._observers:
observer.update(message)主题会保存一个观察者列表,并能一次性通知所有观察者。
创建简单的观察者类:
class EmailNotifier:
def update(self, message):
print(f"Email sent: {message}")
class SMSNotifier:
def update(self, message):
print(f"SMS sent: {message}")每个观察者都有一个 update 方法,在收到通知时会调用它。
使用观察者模式:
# 创建主题对象
news = Subject()
# 创建观察者
email = EmailNotifier()
sms = SMSNotifier()
# 将观察者添加到主题对象
news.add_observer(email)
news.add_observer(sms)
# 通知所有观察者
news.notify("Breaking news: Python is awesome!")创建一个股票价格跟踪器的实用示例:
class Stock:
def __init__(self, symbol, price):
self.symbol = symbol
self._price = price
self._observers = []
def add_observer(self, observer):
self._observers.append(observer)
def set_price(self, price):
self._price = price
self.notify()
def notify(self):
for observer in self._observers:
observer.update(self.symbol, self._price)
class Investor:
def __init__(self, name):
self.name = name
def update(self, symbol, price):
print(f"{self.name} notified: {symbol} is now ${price}")
# 使用股票追踪器
apple_stock = Stock("AAPL", 150)
investor1 = Investor("Alice")
investor2 = Investor("Bob")
apple_stock.add_observer(investor1)
apple_stock.add_observer(investor2)
apple_stock.set_price(155) # 通知所有投资者输出:
Email sent: Breaking news: Python is awesome!
SMS sent: Breaking news: Python is awesome!
Alice notified: AAPL is now $155
Bob notified: AAPL is now $155要点:观察者模式可以让一个对象在发生变化时自动通知多个其他对象。主题对象维护一个观察者列表,并在需要时调用它们的 update 方法。这种模式适用于通知、事件系统,以及让应用程序的多个部分保持同步。
挑战
中等通过创建一个天气监控系统来实现观察者模式。你需要在代码的指定区域创建两个类。
第 1 步:创建 WeatherStation 类
在注释指示的位置编写 WeatherStation 类。这个类应该:
- 继承 Subject 类(使用
class WeatherStation(Subject):) - 初始化时:
- 使用
super().__init__()调用父类构造函数 - 使用单下划线属性
self._temperature将初始温度设为 0(这是 Python 对内部属性的约定)
- 使用
- 实现
set_temperature(self, temperature):- 更新内部温度属性
- 调用
self.notify(self._temperature)通知所有观察者
- 实现
get_temperature(self):- 返回当前温度值
第 2 步:创建 WeatherDisplay 类
在注释指示的位置编写 WeatherDisplay 类。这个类应该:
- 继承 Observer 类(使用
class WeatherDisplay(Observer):) - 初始化时:
- 接收一个
name参数 - 将名称存储为
self.name
- 接收一个
- 实现
update(self, temperature):- 按照下方显示的准确格式打印温度更新消息
消息格式:
显示设备收到温度更新时,必须准确打印:
Display [name]: Current temperature is [temperature]C使用示例:
# Create weather station and displays
station = WeatherStation()
phone_display = WeatherDisplay("Phone")
tablet_display = WeatherDisplay("Tablet")
# Attach displays to station
station.attach(phone_display)
station.attach(tablet_display)
# Update temperature - both displays will be notified
station.set_temperature(25.5)
# Output:
# Display Phone: Current temperature is 25.5C
# Display Tablet: Current temperature is 25.5C重要说明:
attach()和detach()方法已在 Subject 基类中实现,你不需要在 WeatherStation 类中实现或调用它们- 在上面的使用示例中,
station.attach(phone_display)是由使用你这个类的用户调用的,而不是在你的 WeatherStation 实现中调用的 - 你的 WeatherStation 只需在温度变化时调用
self.notify(),其余工作由 Subject 基类处理 - 请按照上面的说明,重点实现 WeatherStation 中要求的三个方法,以及 WeatherDisplay 中要求的两个方法
亲手试试
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self, data):
for observer in self._observers:
observer.update(data)
class Observer:
def update(self, data):
pass
# 在这里编写你的 WeatherStation 类
# 在这里编写你的 WeatherDisplay 类
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Python 在线编译器