教你处理一对多关系 | 观察者模式介绍 (附python代码)

教你处理一对多关系 | 观察者模式介绍 (附python代码)
最新回答
云终韵

2026-10-20 18:57:21

观察者模式是一种处理一对多关系的经典设计模式,通过定义对象间的依赖关系,使主题(Subject)状态变化时能自动通知所有观察者(Observer)并更新。以下从核心概念、错误示范、解决方案及代码实现展开介绍:

一、一对多关系与观察者模式的核心
  • 一对多关系:一个主题对象的状态变化会触发多个观察者对象的响应。例如气象站中,天气数据(主题)变化时,所有布告板(观察者)需同步更新。
  • 角色分工:

    主题(Subject):维护观察者列表,提供注册/删除观察者的接口,并在状态变化时通知所有观察者。

    观察者(Observer):定义统一的更新接口(如update()),供主题调用以完成自身状态更新。

  • 松耦合优势:主题无需知道观察者的具体实现细节,仅需调用其接口,实现解耦。
二、错误示范:硬编码观察者

以下代码直接在主题类中硬编码观察者实例,导致扩展性差:

class WeatherData: def __init__(self): self.currentConditionsDisplay = Display(name='CurrentConditions') self.statisticsDisplay = Display(name='Statistics') self.forecastDisplay = Display(name='Forecast') def measurementsChanged(self): temp, humidity, pressure = getTemperature(), getHumidity(), getPressure() self.currentConditionsDisplay.update(temp, humidity, pressure) # 硬编码调用 self.statisticsDisplay.update(temp, humidity, pressure) self.forecastDisplay.update(temp, humidity, pressure)

问题:

  • 新增观察者需修改主题代码,违反开闭原则。
  • 无法在运行时动态增删观察者。
三、观察者模式的解决方案

通过维护观察者列表并动态通知,实现灵活扩展:

1. 主题类实现class WeatherData: def __init__(self): self.observers = [] # 存储观察者 self.temp = self.humidity = self.pressure = None def registerObserver(self, observer): # 注册观察者 self.observers.append(observer) def removeObserver(self, index): # 删除观察者 if 0 <= index < len(self.observers): self.observers.pop(index) def notifyObservers(self): # 通知所有观察者 for observer in self.observers: observer.update(self.temp, self.humidity, self.pressure) def measurementsChanged(self): # 状态变化时触发通知 self.temp, self.humidity, self.pressure = getTemperature(), getHumidity(), getPressure() self.notifyObservers()2. 观察者基类与具体实现class Observer: def __init__(self, name): self.name = name def update(self, temp, humidity, pressure): # 统一更新接口 print(f"{self.name}: Temp={temp}, Humidity={humidity}, Pressure={pressure}")# 示例:注册多个观察者if __name__ == "__main__": weather_data = WeatherData() weather_data.registerObserver(Observer("CurrentConditions")) weather_data.registerObserver(Observer("Statistics")) weather_data.measurementsChanged() # 输出所有观察者更新信息四、关键点总结
  1. 动态管理观察者:

    通过registerObserver()和removeObserver()实现运行时增删。

    新增观察者无需修改主题代码,只需调用注册方法。

  2. 通知机制:

    主题状态变化时调用notifyObservers(),遍历列表并调用每个观察者的update()方法。

  3. 松耦合设计:

    主题仅依赖观察者的update()方法,不关心其内部逻辑。

    观察者无需知道主题的具体实现,仅需响应通知。

五、应用场景与优势
  • 场景:

    事件处理系统(如GUI按钮点击)。

    模型-视图分离(如MVC模式中的视图更新)。

    日志记录(如将日志输出到文件、数据库等多目标)。

  • 优势:

    可扩展性强:新增观察者不影响现有代码。

    解耦:降低主题与观察者间的依赖度。

    复用性:同一观察者可订阅多个主题。

六、完整代码示例# 辅助函数def getTemperature(): return 72def getHumidity(): return 60def getPressure(): return 1000# 主题类class WeatherData: def __init__(self): self.observers = [] self.temp = self.humidity = self.pressure = None def registerObserver(self, observer): self.observers.append(observer) def removeObserver(self, index): if 0 <= index < len(self.observers): self.observers.pop(index) def notifyObservers(self): for observer in self.observers: observer.update(self.temp, self.humidity, self.pressure) def measurementsChanged(self): self.temp, self.humidity, self.pressure = getTemperature(), getHumidity(), getPressure() self.notifyObservers()# 观察者类class Observer: def __init__(self, name): self.name = name def update(self, temp, humidity, pressure): print(f"{self.name}: Temp={temp}, Humidity={humidity}, Pressure={pressure}")# 测试if __name__ == "__main__": weather_data = WeatherData() weather_data.registerObserver(Observer("Display1")) weather_data.registerObserver(Observer("Display2")) weather_data.measurementsChanged()

通过观察者模式,可高效实现一对多关系的动态管理,提升代码的可维护性与扩展性。