您的位置:首页 > 编程语言 > Python开发

Head First 设计模式——观察者模式(Observer Pattern)——Python实现(2)

2011-06-14 10:35 826 查看
本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 Unported许可协议进行许可。允许非商业转载,但应注明作者及出处。

作者: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))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐