本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 Unported许可协议进行许可。允许非商业转载,但应注明作者及出处。
作者:liuyuan_jq
2011-06-14
上节的例子中有两个缺点:
1. 上个例子中我们采用的是推的方式,当主题对象的数据更新时,所有的观察者对象的数据都必须更新。但是主题对象传递给观察者的数据可能不是某些观察者想要的或者观察者只是使用其中一部分数据。在这种情况下,观察者对象会强迫收到一些无用的数据。
2. 当主题对象的数据更新时,所有的观察者对象都必须立即更新。气象站测试非常敏锐,以至于温度计读数每十分之一度都会更新,这会造成WeatherData对象持续不断地通知观察者,我们并不希望看到这样的事情发生。如果我们希望半度以上才更新,就可以在温度差距到达半度时,调用setChanged(),进行有效的更新。
解决方案:
1. 如果观察者对象经常收到一些无用的信息,则可以采用拉的方式,主动地从主题对象获得消息。主题对象可以提供一些getter方法来满足要求。
2. 可以增加一个setChanged()方法,用来标记主题对象状态已经改变的事实,让notifyObservers()知道当它被调用时应该更新观察者。如果调用notifyObservers()之前没有先调用setChanged(),则观察者就不会被通知。你也许不会用到此功能,但是添加这样的功能,当需要时就可以使用,让你的系统可以更有弹性。
源码
weatherData.py
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