设为首页 收藏本站
查看: 555|回复: 0

[经验分享] Head First 设计模式——观察者模式(Observer Pattern)——Python实现(2)

[复制链接]

尚未签到

发表于 2017-5-8 10:25:07 | 显示全部楼层 |阅读模式
  本作品采用知识共享署名-非商业性使用-相同方式共享 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 Subjectclass WeatherData(Subject):"""天气数据类,是一个主题类"""# 类静态成员observers = []changed = Falsedef __init__(self):self.temperature = 0.0self.humidity    = 0.0self.pressure    = 0.0def 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 = temperatureself.humidity    = humidityself.pressure    = pressureself.measurementsChanged()def getTemperature(self):return self.temperaturedef getHumidity(self):return self.humiditydef getPressure(self):return self.pressuredef setChanged(self):self.changed = Truedef clearChanged(self):self.changed = Falsedef hasChanged(self):return self.changed
displayElement.py
#!/usr/bin/env python# -*- coding:utf-8 -*-from observer import Observerfrom weatherData import WeatherDataclass DisplayElement(object):def display(self):raise NotImplementedError("abstract DisplayElement")class CurrentConditionsDisplay(Observer, DisplayElement):"""目前状况布告板"""def __init__(self, weatherData):self.weatherData = weatherDataself.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 = weatherDataself.currentPressure = 29.92self.weatherData.registerObserver(self)def update(self):self.lastPressure    = self.currentPressureself.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.0self.minTemp = 200self.tempSum = 0.0self.numReadings = 0self.weatherData = weatherDataself.weatherData.registerObserver(self)def update(self):temp = self.weatherData.getTemperature()self.tempSum += tempself.numReadings += 1if temp > self.maxTemp:self.maxTemp = tempif temp < self.minTemp:self.minTemp = tempself.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 = weatherDataself.weatherData.registerObserver(self)self.heatIndex = 0.0def 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))

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-374552-1-1.html 上篇帖子: (转)python 函数参数的传递(参数带星号的说明) 下篇帖子: 用python写的开心网收菜偷菜的小工具
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表