python-观察者模式
源码地址:https://github.com/weilanhanf/PythonDesignPatterns
说明:
存在这样的一种情况:公司领导再开例会那天临时有事,他让秘书给所有会上员工群发了一封邮件,通知大家会议取消,员工们收到邮件之后得知会议取消便继续回到各自岗位开始工作。这其中就包含了一种隐含地思想就是:领导与员工们之间的“一对多的通知依赖关系”。即一个对象的状态或行为的变化将导致其他对象的状态或行为也发生改变,它们之间将产生联动。
观察者模式:
定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并被自动更新。发生改变的对象称为观察目标,被通知的对象称为观察者 。一个观察目标可以对应多个观察者
观察者模式的结构
观察者模式包含以下4个角色: Subject(目标) ConcreteSubject(具体目标) Observer(观察者) ConcreteObserver(具体观察者)
实例:
"""
在门面模式中,我们提到过火警报警器。在当时,我们关注的是通过封装减少代码重复。
而今天,我们将从业务流程的实现角度,来再次实现该火警报警器。
""" class AlarmSensor:
def run(self):
print("Alarm Ring...")
class WaterSprinker:
def run(self):
print("Spray Water...")
class EmergencyDialer:
def run(self):
print("Dial 119...") """
以上是门面模式中的三个传感器类的结构。
仔细分析业务,报警器、洒水器、拨号器都是“观察”烟雾传感器的情况来做反应的。
因而,他们三个都是观察者,而烟雾传感器则是被观察对象了。
根据分析,将三个类提取共性,泛化出“观察者”类,并构造被观察者。
观察者如下:
""" class Observer:
def update(self):
pass
class AlarmSensor(Observer):
def update(self,action):
print("Alarm Got: %s" % action)
self.runAlarm()
def runAlarm(self):
print("Alarm Ring...")
class WaterSprinker(Observer):
def update(self,action):
print("Sprinker Got: %s" % action)
self.runSprinker()
def runSprinker(self):
print("Spray Water...")
class EmergencyDialer(Observer):
def update(self,action):
print("Dialer Got: %s"%action)
self.runDialer()
def runDialer(self):
print("Dial 119...") """
观察者中定义了update接口,如果被观察者状态比较多,或者每个具体的观察者方法比较多,
可以通过update传参数进行更丰富的控制。
下面构造被观察者。
""" class Observed:
observers=[]
action=""
def addObserver(self,observer):
self.observers.append(observer)
def notifyAll(self):
for obs in self.observers:
obs.update(self.action)
class smokeSensor(Observed):
def setAction(self,action):
self.action=action
def isFire(self):
return True """
被观察者中首先将观察对象加入到观察者数组中,若发生情况,则通过notifyAll通知各观察者。
业务代码如下:
""" if __name__=="__main__":
alarm=AlarmSensor()
sprinker=WaterSprinker()
dialer=EmergencyDialer() smoke_sensor=smokeSensor()
smoke_sensor.addObserver(alarm)
smoke_sensor.addObserver(sprinker)
smoke_sensor.addObserver(dialer) if smoke_sensor.isFire():
smoke_sensor.setAction("On Fire!")
smoke_sensor.notifyAll()
打印结果:
Alarm Got: On Fire!
Alarm Ring...
Sprinker Got: On Fire!
Spray Water...
Dialer Got: On Fire!
Dial 119...
模式优点
可以实现表示层和数据逻辑层的分离 在观察目标和观察者之间建立一个抽象的耦合 支持广播通信,简化了一对多系统设计的难度 符合开闭原则,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便
模式缺点
将所有的观察者都通知到会花费很多时间 如果存在循环依赖时可能导致系统崩溃 没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而只是知道观察目标发生了变化
模式适用环境
一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用 一个对象的改变将导致一个或多个其他对象发生改变,且并不知道具体有多少对象将发生改变,也不知道这些对象是谁 需要在系统中创建一个触发链
python-观察者模式的更多相关文章
- 设计模式(Python)-观察者模式
本系列文章是希望将软件项目中最常见的设计模式用通俗易懂的语言来讲解清楚,并通过Python来实现,每个设计模式都是围绕如下三个问题: 为什么?即为什么要使用这个设计模式,在使用这个模式之前存在什么样的 ...
- [python实现设计模式]-4.观察者模式-吃食啦!
观察者模式是一个非常重要的设计模式. 我们先从一个故事引入. 工作日的每天5点左右,大燕同学都会给大家订饭. 然后7点左右,饭来了. 于是燕哥大吼一声,“饭来啦!”,5点钟定过饭的同学就会纷纷涌入餐厅 ...
- python设计模式之观察者模式
观察者模式 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern).比如,当一个对象被修改时,则会自动通知它的依赖对象.观察者模式属于行为型模式. 观察者模式在状态检测和事件处 ...
- python设计模式第十天【观察者模式】
1.应用场景 (1)监听事件驱动程序中的外部事件 (2)监听某个对象的状态变化 (3)发布-订阅模型中,消息出现时通知邮件列表中的订阅者 2. 观察者模式UML图 3. 代码实现: #!/usr/bi ...
- python 设计模式之观察者模式
观察者模式是一个软件设计模式,一个主题对象博包涵一系列依赖他的观察者,自动通知观察者的主题对象的改变,通常会调用每个观察者的一个方法.这个设计模式非常适用于分布式事件处理系统. 典型的在观察者模式下: ...
- python实现观察者模式
python实现观察者模式 前言 有时,我们希望在一个对象的状态改变时更新另外一组对象.在MVC模式中有这样一个非 常常见的例子,假设在两个视图(例如,一个饼图和一个电子表格)中使用同一个模型的数据, ...
- python设计模式---行为型之观察者模式
比较常用咯~~ from django.test import TestCase from abc import ABCMeta, abstractmethod # 行为型设计模式---观察者模式 c ...
- 观察者模式的python实现
什么会观察者模式?观察者模式就是订阅-推送模式.是为了解耦合才会被利用起来的设计模式. 经典的就是boss 前台和员工之间的故事.一天A员工在看电影,B员工在看动漫,但是两人担心boss来了,自己没及 ...
- [Python设计模式] 第14章 老板来了——观察者模式
github地址:https://github.com/cheesezh/python_design_patterns 题目 用程序模拟以下情景,在一个办公室里,当老板进门的时候,前台秘书就偷偷通知办 ...
- Python 高级编程 ——观察者模式
观察者模式的定义 :定义了对象之间一对多依赖,当一个对象改变状态时,这个对象的所有依赖者都会收到通知并按照自己的方式进行更新. 按照一个气象站的例子来看观察者模式 从气象站取得数据后要在三个布告牌显示 ...
随机推荐
- dubbo实现原理之SPI简介
dubbo采用微内核+插件体系,设计优雅,扩展性很强.微内核+插件体系是如何实现的呢?想必大家都知道SPI(service provider interface)机制.这种机制的原理是假如我们定义了服 ...
- centos7 系统优化
#!/usr/bin/env bash #设置环境变量 export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/u ...
- javascript数据结构与算法---二叉树(查找最小值、最大值、给定值)
javascript数据结构与算法---二叉树(查找最小值.最大值.给定值) function Node(data,left,right) { this.data = data; this.left ...
- Scala使用Akka模拟RPC机制代码2
RemoteMessage.scala //对象要序列化才能通过网络传输 这个地方没有大括号....这有这个extends声明 trait RemoteMessage extends Serializ ...
- java和js获取当前天之后或之前7天(任意)日期
一.获取过去第几天的日期(- 操作) 或者 未来 第几天的日期( + 操作) /** * 获取过去第几天的日期(- 操作) 或者 未来 第几天的日期( + 操作) * * @param past * ...
- MySQL笔记(3)---文件
1.前言 第二章简单记录了一下InnoDB存储引擎的一个基本内容,介绍了保证高效插入的Insert Buffer,change Buffer和确保数据安全的write ahead log以及doubl ...
- CentOS7下RabbitMQ服务安装配置
参考文档: CentOS7下RabbitMQ服务安装配置 http://www.linuxidc.com/Linux/2016-03/129557.htm 在linux下安装配置rabbitMQ详细教 ...
- 从学CodeSmith谈程序员学习方法
一直觉得CodeSmith是个好东西,最近正好有点时间来研究下,其实以前也想学习怎么用,在博客园搜一下有很多介绍CodeSmith的文章,我就收藏过一个写得很详细的http://terrylee.cn ...
- Android H5调起原生微信或支付宝支付
Android H5调起原生微信或支付宝支付 WebView调用原生微信或支付宝回调:其原理就是在shouldOverrideUrlLoading(final WebView view, String ...
- Javac中的方法
例1: interface IA{ void m(int a); } abstract class AC implements IA{ // 这个抽象方法覆盖了 IA中的方法m public abst ...