Head First 设计模式——观察者模式(Observer Pattern)——Python实现(2)
2011-06-14 10:35
826 查看
本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 Unported许可协议进行许可。允许非商业转载,但应注明作者及出处。
作者:liuyuan_jq
2011-06-14
2. 当主题对象的数据更新时,所有的观察者对象都必须立即更新。气象站测试非常敏锐,以至于温度计读数每十分之一度都会更新,这会造成WeatherData对象持续不断地通知观察者,我们并不希望看到这样的事情发生。如果我们希望半度以上才更新,就可以在温度差距到达半度时,调用setChanged(),进行有效的更新。
2. 可以增加一个setChanged()方法,用来标记主题对象状态已经改变的事实,让notifyObservers()知道当它被调用时应该更新观察者。如果调用notifyObservers()之前没有先调用setChanged(),则观察者就不会被通知。你也许不会用到此功能,但是添加这样的功能,当需要时就可以使用,让你的系统可以更有弹性。
displayElement.py
作者:liuyuan_jq
2011-06-14
上节的例子中有两个缺点:
1. 上个例子中我们采用的是推的方式,当主题对象的数据更新时,所有的观察者对象的数据都必须更新。但是主题对象传递给观察者的数据可能不是某些观察者想要的或者观察者只是使用其中一部分数据。在这种情况下,观察者对象会强迫收到一些无用的数据。2. 当主题对象的数据更新时,所有的观察者对象都必须立即更新。气象站测试非常敏锐,以至于温度计读数每十分之一度都会更新,这会造成WeatherData对象持续不断地通知观察者,我们并不希望看到这样的事情发生。如果我们希望半度以上才更新,就可以在温度差距到达半度时,调用setChanged(),进行有效的更新。
解决方案:
1. 如果观察者对象经常收到一些无用的信息,则可以采用拉的方式,主动地从主题对象获得消息。主题对象可以提供一些getter方法来满足要求。2. 可以增加一个setChanged()方法,用来标记主题对象状态已经改变的事实,让notifyObservers()知道当它被调用时应该更新观察者。如果调用notifyObservers()之前没有先调用setChanged(),则观察者就不会被通知。你也许不会用到此功能,但是添加这样的功能,当需要时就可以使用,让你的系统可以更有弹性。
源码
weatherData.py#!/usr/bin/env python # -*- coding:utf-8 -*- from subject import Subject class WeatherData(Subject): """ 天气数据类,是一个主题类 """ # 类静态成员 observers = [] changed = False def __init__(self): self.temperature = 0.0 self.humidity = 0.0 self.pressure = 0.0 def registerObserver(self, observer): """ 注册观察者对象 """ self.observers.append(observer) def removeObserver(self, observer): """ 注销观察者对象 """ self.observers.remove(observer) def notifyObservers(self): """ 通知所有的观察者对象 """ if self.hasChanged(): for observer in self.observers: observer.update() self.clearChanged() def measurementsChanged(self): self.setChanged() self.notifyObservers() self.clearChanged() def setMeasurements(self, temperature, humidity, pressure): self.temperature = temperature self.humidity = humidity self.pressure = pressure self.measurementsChanged() def getTemperature(self): return self.temperature def getHumidity(self): return self.humidity def getPressure(self): return self.pressure def setChanged(self): self.changed = True def clearChanged(self): self.changed = False def hasChanged(self): return self.changed
displayElement.py
#!/usr/bin/env python # -*- coding:utf-8 -*- from observer import Observer from weatherData import WeatherData class DisplayElement(object): def display(self): raise NotImplementedError("abstract DisplayElement") class CurrentConditionsDisplay(Observer, DisplayElement): """ 目前状况布告板 """ def __init__(self, weatherData): self.weatherData = weatherData self.weatherData.registerObserver(self) def update(self): self.temperature = self.weatherData.getTemperature() self.humidity = self.weatherData.getHumidity() self.display() def display(self): print("Current conditions: " + str(self.temperature) + "F degrees and " + str(self.humidity) + "% humidity") class ForecastDisplay(Observer, DisplayElement): """ 天气预报布告板 """ def __init__(self, weatherData): self.weatherData = weatherData self.currentPressure = 29.92 self.weatherData.registerObserver(self) def update(self): self.lastPressure = self.currentPressure self.currentPressure = self.weatherData.getPressure() self.display() def display(self): print("Forecast: "); if self.currentPressure > self.lastPressure: print("Improving weather on the way!") elif self.currentPressure == self.lastPressure: print("More of the same") elif self.currentPressure < self.lastPressure: print("Watch out for cooler, rainy weather") class StatisticsDisplay(Observer, DisplayElement): """ 气象统计布告板 """ def __init__(self, weatherData): self.maxTemp = 0.0 self.minTemp = 200 self.tempSum = 0.0 self.numReadings = 0 self.weatherData = weatherData self.weatherData.registerObserver(self) def update(self): temp = self.weatherData.getTemperature() self.tempSum += temp self.numReadings += 1 if temp > self.maxTemp: self.maxTemp = temp if temp < self.minTemp: self.minTemp = temp self.display() def display(self): print("Avg/Max/Min temperature = " + str(self.tempSum / self.numReadings) + "/" + str(self.maxTemp) + "/" + str(self.minTemp)) class HeatIndexDisplay(Observer, DisplayElement): """ 酷热指数布告板 """ def __init__(self, weatherData): self.weatherData = weatherData self.weatherData.registerObserver(self) self.heatIndex = 0.0 def update(self): t = self.weatherData.getTemperature() rh = self.weatherData.getHumidity() self.heatIndex = self._computeHeatIndex(t, rh) self.display() def _computeHeatIndex(self, t, rh): index = ( (16.923 + (0.185212 * t)) + (5.37941 * rh) - (0.100254 * t * rh) + (0.00941695 * (t * t)) + (0.00728898 * (rh * rh)) + (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) + (0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 * (rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) + (0.000000197483 * (t * rh * rh * rh)) - (0.0000000218429 * (t * t * t * rh * rh)) + (0.000000000843296 * (t * t * rh * rh * rh)) - (0.0000000000481975 * (t * t * t * rh * rh * rh)) ) return float(index) def display(self): print("Heat index is " + str(self.heatIndex))
相关文章推荐
- Head First 设计模式——观察者模式(Observer Pattern)——Python实现(3)
- Head First 设计模式——观察者模式(Observer Pattern)——Python实现(1)
- Head First 设计模式 (二) 观察者模式(observer pattern) C++实现
- 我所理解的设计模式(C++实现)——观察者模式(Observer Pattern)
- 我所理解的设计模式(C++实现)——观察者模式(Observer Pattern)
- Head First 设计模式——装饰器(Decorator Pattern)——Python实现
- 设计模式——行为型设计模之借助观察者模式(Observer Pattern)实现模块之间的解耦(四)
- 我所理解的设计模式(C++实现)——观察者模式(Observer Pattern) (转)
- 我所理解的设计模式(C++实现)——观察者模式(Observer Pattern)
- 我所理解的设计模式(C++实现)——观察者模式(Observer Pattern)
- Head First 设计模式——策略模式(Strategy Pattern)——Python实现
- Head First 设计模式——观察者模式(Observer Pattern) 之二
- 【设计模式】观察者模式(observer)c#/python实现
- 我理解设计模式C++实现观察者模式Observer Pattern
- 【设计模式】设计模式C++编程实现之观察者模式(ObserverPattern)
- 我所理解的设计模式(C++实现)——观察者模式(Observer Pattern)
- 【设计模式】设计模式C++编程实现之观察者模式(ObserverPattern)
- 【设计模式】设计模式C++编程实现之观察者模式(ObserverPattern)
- 我所理解的设计模式(C++实现)——观察者模式(Observer Pattern)
- 我所理解的设计模式(C++实现)——观察者模式(Observer Pattern)