背景
WeatherData对象取得温度、湿度、气压数据,随后更新到三个布告板显示:目前状况、气象统计、天气预报
当有新的测量数据时,WeatherData的measuremeentsChanged方法就会被调用
1.0版本:错误示范
class WeatherData:
def measurementsChanged(self):
temp = self.getTemperature();
humidity = self.getHumidity();
pressure = self.getPerssure();
currentConditionsDisplay.update(temp, humidity, pressure);
statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
针对具体实现编程,增删布告板必须修改程序
三个update方法是可能改变的地方,没有封装起来
2.0版本:
观察者模式
观察者模式定义了对象之间的一对多依赖。当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新
主题Subject管理数据,当主题对象数据改变时,通知观察者新数据
观察者Observer可以注册主题或取消注册,接收到新数据进行处理
类图
优点:主题和观察者之间的松耦合
当有新的观察者时,主题对象不需要修改,只需要新增观察者,并且自己注册为观察者
当观察者变化时,主题对象不需要修改,主题只会通知观察者列表里的对象
当主题对象数据逻辑修改时,观察者不需要修改,观察者只接受数据
在其他地方,可以独立的复用主题或观察者
设计气象站
实现气象站
class WeatherData:
def __init__(self):
self.observers = []
self.temperature, self.humidity, self.pressure = 0, 0, 0
def registerObserver(self, observer):
self.observers.append(observer)
def removeObserver(self, observer):
if observer in self.observers:
self.observers.remove(observer)
def notifyObservers(self):
for observer in self.observers:
observer.update(self.temperature, self.humidity, self.pressure)
def measurementsChanged(self):
self.notifyObservers()
def setMeasurements(self, temperature, humidity, pressure):
# test
self.temperature, self.humidity, self.pressure = temperature, humidity, pressure
self.measurementsChanged()
class CurrentConditionsDisplay:
def __init__(self, weatherData):
self.temperature, self.humidity = 0, 0
self.weatherData = weatherData
self.weatherData.registerObserver(self)
def update(self, temperature, humidity, pressure):
self.temperature, self.humidity = temperature, humidity
self.display()
def display(self):
print('Current conditions: {}F degrees and {}% humdity'.format(self.temperature, self.humidity))
if __name__ == '__main__':
weatherDate = WeatherData()
currentDisplay = CurrentConditionsDisplay(weatherDate)
weatherDate.setMeasurements(2, 4, 6)
weatherDate.setMeasurements(1, 34, 46)
3.0版本
增加setchanged方法
可以在更新观察者时,有更多的弹性。比方说,温度计相差半度以上再更新
class WeatherData:
def __init__(self):
self.observers = []
self.temperature, self.humidity, self.pressure = 0, 0, 0
self.changed = False
self.MINI_TEMPERATURE_DIFF = 0.5
def registerObserver(self, observer):
self.observers.append(observer)
def removeObserver(self, observer):
if observer in self.observers:
self.observers.remove(observer)
def notifyObservers(self):
for observer in self.observers:
observer.update(self.temperature, self.humidity, self.pressure)
def setChanged(self, temperature, humidity, pressure):
if abs(temperature - self. temperature) > self.MINI_TEMPERATURE_DIFF:
self.temperature, self.humidity, self.pressure = temperature, humidity, pressure
self.changed = True
def clearChange(self):
self.changed = False
def hasChange(self):
return self.changed
def measurementsChanged(self):
if self.hasChange():
self.notifyObservers()
self.clearChange()
def setMeasurements(self, temperature, humidity, pressure):
# test
self.setChanged(temperature, humidity, pressure)
self.measurementsChanged()
主题推送数据改为观察者拉取数据
好处:观察者不必接受不需要的状态数据;主题新增状态数据时不需要修改所有的观察者调用,只需要新增getter方法;
缺点:观察者多次调用才能凑齐所有需要的数据
class WeatherData:
def __init__(self):
self.observers = []
self.temperature, self.humidity, self.pressure = 0, 0, 0
self.changed = False
self.MINI_TEMPERATURE_DIFF = 0.5
def registerObserver(self, observer):
self.observers.append(observer)
def removeObserver(self, observer):
if observer in self.observers:
self.observers.remove(observer)
def notifyObservers(self):
for observer in self.observers:
observer.update(self)
def setChanged(self, temperature, humidity, pressure):
if abs(temperature - self. temperature) > self.MINI_TEMPERATURE_DIFF:
self.temperature, self.humidity, self.pressure = temperature, humidity, pressure
self.changed = True
def clearChange(self):
self.changed = False
def hasChange(self):
return self.changed
def getTemperature(self):
return self.temperature
def getHumidity(self):
return self.humidity
def getPressure(self):
return self.pressure
def measurementsChanged(self):
if self.hasChange():
self.notifyObservers()
self.clearChange()
def setMeasurements(self, temperature, humidity, pressure):
# test
self.setChanged(temperature, humidity, pressure)
self.measurementsChanged()
class CurrentConditionsDisplay:
def __init__(self, obs):
self.temperature, self.humidity = 0, 0
self.obs = obs
self.obs.registerObserver(self)
def update(self, obs):
if isinstance(obs, WeatherData):
self.temperature, self.humidity = obs.getTemperature(), obs.getHumidity()
self.display()
def display(self):
print('Current conditions: {}F degrees and {}% humdity'.format(self.temperature, self.humidity))
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。