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

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

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

作者:liuyuan_jq
2011-06-13

观察者模式定义

定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖都会收到通知并自动更新。观察者模式提供了一种对象设计,让主题和观察者之间松耦合。

设计原则

为了交互对象之间的松耦合设计而努力。松耦合的设计之所以能让我们建立有弹性的系统,能够应对变化,是因为对象之间的互相依赖降到了最低。

问题

建立下一代Internet气象观察站,该气象站必须建立在我们专利申请中的WeatherData对象上,由WeatherData对象负责追踪目前的天气状况(温度,湿度,气压)。

建立一个应用,有三种布告板,分别显示目前的状态、气象统计及简单的预报。

当WeatherObject对象获得最新的测量数据时,三种布告板必须实时更新。

公布一组API,让其他开发人员可以写出自己的气象布告板。

设计气象站

WeatherData实现Subject接口

class Subject(object):
"""
主题接口类
"""
def registerObserver(observer):
raise NotImplementedError("abstract Subject")
def removeObserver(observer):
raise NotImplementedError("abstract Subject")
def notifyObservers(self):
raise NotImplementedError("abstract Subject")


气象组件实现观察者接口

class Observer(object):
"""
观察者接口类
"""
def update(temp, humidity, pressure):
raise NotImplementedError("abstract Observer")


布告栏显示接口

class DisplayElement(object):
def display(self):
raise NotImplementedError("abstract DisplayElement")


源代码具体实现

subject.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Subject(object): """ 主题接口类 """ def registerObserver(observer): raise NotImplementedError("abstract Subject") def removeObserver(observer): raise NotImplementedError("abstract Subject") def notifyObservers(self): raise NotImplementedError("abstract Subject")


observer.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Observer(object): """ 观察者接口类 """ def update(temp, humidity, pressure): raise NotImplementedError("abstract Observer")


weatherData.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from subject import Subject
class WeatherData(Subject):
"""
天气数据类,是一个主题类
"""
# 类静态成员
observers = []

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):
"""
通知所有的观察者对象
"""
for observer in self.observers:
observer.update(self.temperature, self.humidity, self.pressure)
def measurementsChanged(self):
self.notifyObservers()

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


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, temperature, humidity, pressure):
self.temperature = temperature
self.humidity = humidity
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, temp, humidity, pressure):
self.lastPressure = self.currentPressure
self.currentPressure = pressure
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, humidity, pressure):
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, rh, pressure):
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))


测试

weatherStation.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from weatherData import WeatherData
from displayElement import *
weatherData = WeatherData()
currentDisplay    = CurrentConditionsDisplay(weatherData)
statisticsDisplay = StatisticsDisplay(weatherData)
forecastDisplay   = ForecastDisplay(weatherData)
weatherData.setMeasurements(80, 65, 30.4)
weatherData.setMeasurements(82, 70, 29.2)
weatherData.setMeasurements(78, 90, 29.2)


Current conditions: 80F degrees and 65% humidity
Avg/Max/Min temperature = 80.0/80/80
Forecast:
Improving weather on the way!
Current conditions: 82F degrees and 70% humidity
Avg/Max/Min temperature = 81.0/82/80
Forecast:
Watch out for cooler, rainy weather
Current conditions: 78F degrees and 90% humidity
Avg/Max/Min temperature = 80.0/82/78
Forecast:
More of the same


weatherStationHeatIndex.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from weatherData import WeatherData
from displayElement import *
weatherData = WeatherData()
currentDisplay    = CurrentConditionsDisplay(weatherData)
statisticsDisplay = StatisticsDisplay(weatherData)
forecastDisplay   = ForecastDisplay(weatherData)
heatIndexDisplay  = HeatIndexDisplay(weatherData)
weatherData.setMeasurements(80, 65, 30.4)
weatherData.setMeasurements(82, 70, 29.2)
weatherData.setMeasurements(78, 90, 29.2)


Current conditions: 80F degrees and 65% humidity
Avg/Max/Min temperature = 80.0/80/80
Forecast:
Improving weather on the way!
Heat index is 82.9553506371
Current conditions: 82F degrees and 70% humidity
Avg/Max/Min temperature = 81.0/82/80
Forecast:
Watch out for cooler, rainy weather
Heat index is 86.9012330639
Current conditions: 78F degrees and 90% humidity
Avg/Max/Min temperature = 80.0/82/78
Forecast:
More of the same
Heat index is 83.6496713956
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐