Python笔记之观察者模式


Posted in Python onNovember 20, 2019

观察者模式中的主题对象一般存在着一个其他服务依赖的核心服务,并且维护着其他依赖此核心服务的对象列表(即观察者或监视者列表),当主题对象发生变化时,观察者应该改变自己的状态或者进行某些操作

观察者模式中的三个角色:

  • 主题:即观察者观察的对象,一般是需要有注册和注销方法,用来添加观察者和删除观察者。
  • 观察者基类:这个类主要是需要定义一个接口,以便主题发生变化时可以得到对应的通知信息。
  • 观察者:这个类需要具体实现基类中的“通知”接口,以便和主题的变化保持同步。

主题的两种通知方式:

  • 拉模型:这个方式重心在观察者上,当主题发生变化时,会广播所有的观察者,然后由观察者来获取相应的数据。
  • 推模型:这个方式重心在主题上,当主题发生变化时,主题将根据观察者的需要将自身的变化推送给需要的观察者。

观察者模式的优点:

  • 观察者模式中彼此交互的对象都是保持松耦合的。主题对观察者唯一的了解就是观察者实现的“通知”接口,除此之外它们之间都是互不影响且独立存在的,可以根据需要对自身作出修改。
  • 可以随时添加或删除观察者。
  • 这种模式下,可以在很少甚至不修改主题或观察者的情况下进行对象之间高效的数据发送。

其他注意点:

  • 观察者模式中是可以有多个主题和多个观察者之间的对应关系的,但是一定要弄清楚它们之间的关系以及变化,不然就会变得非常复杂。
  • 一般情况是由主题来触发“通知”方法的,但是在特殊情况下也可以由观察者来触发“通知”方法。

简单示例:

from abc import ABCMeta, abstractmethod


class Publisher:
  """被观察者:发布/订阅关系中的发布对象"""
  def __init__(self):
    self.subscribers = []
    self.latest_content = None

  def set_content(self, content):
    """有新消息时,发布新的消息"""
    self.latest_content = content
    self.publish()

  def get_latest_content(self):
    """获取最新的消息"""
    return self.latest_content

  def register(self, subscriber):
    """注册一个新的订阅者"""
    self.subscribers.append(subscriber)

  def publish(self):
    """发布消息并通知订阅的用户"""
    for subscriber in self.subscribers:
      subscriber.notify()


class Subscriber(metaclass=ABCMeta):
  """观察者的抽象类:需要定义一个通知接口,用于发布对象通知订阅的用户"""
  @abstractmethod
  def notify(self):
    pass


class SubscriberA(Subscriber):
  """观察者A:发布/订阅关系中的订阅者,当订阅的发布者有新的变化或动态的时候能及时收到通知"""
  def __init__(self):
    self.my_publisher = None

  def subscribe(self, publisher):
    """订阅并进行注册"""
    self.my_publisher = publisher
    self.my_publisher.register(self)

  def notify(self):
    """获取最新消息"""
    latest_content = self.my_publisher.get_latest_content()
    print(self, latest_content)


class SubscriberB(Subscriber):
  """观察者B:发布/订阅关系中的订阅者,当订阅的发布者有新的变化或动态的时候能及时收到通知"""
  def __init__(self):
    self.my_publisher = None

  def subscribe(self, publisher):
    """订阅并进行注册"""
    self.my_publisher = publisher
    self.my_publisher.register(self)

  def notify(self):
    """获取最新消息"""
    latest_content = self.my_publisher.get_latest_content()
    print(self, latest_content)


if __name__ == '__main__':
  new_publisher = Publisher()
  subscriber_a = SubscriberA()
  subscriber_a.subscribe(new_publisher)
  subscriber_b = SubscriberB()
  subscriber_b.subscribe(new_publisher)
  new_publisher.set_content('This is a new message!')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
linux系统使用python获取内存使用信息脚本分享
Jan 15 Python
python中 chr unichr ord函数的实例详解
Aug 06 Python
Python获取系统所有进程PID及进程名称的方法示例
May 24 Python
python  创建一个保留重复值的列表的补码
Oct 15 Python
python接口自动化(十六)--参数关联接口后传(详解)
Apr 16 Python
python中的TCP(传输控制协议)用法实例分析
Nov 15 Python
使用Python来做一个屏幕录制工具的操作代码
Jan 18 Python
Spring Boot中使用IntelliJ IDEA插件EasyCode一键生成代码详细方法
Mar 20 Python
Python实现爬取网页中动态加载的数据
Aug 17 Python
python boto和boto3操作bucket的示例
Oct 30 Python
Python天气语音播报小助手
Sep 25 Python
Python基本的内置数据类型及使用方法
Apr 13 Python
django 实现celery动态设置周期任务执行时间
Nov 19 #Python
python调用接口的4种方式代码实例
Nov 19 #Python
Python Django2.0集成Celery4.1教程
Nov 19 #Python
通过celery异步处理一个查询任务的完整代码
Nov 19 #Python
Django 自动生成api接口文档教程
Nov 19 #Python
wxpython实现按钮切换界面的方法
Nov 19 #Python
Python性能分析工具Profile使用实例
Nov 19 #Python
You might like
Zend Studio 无法启动的问题解决方法
2008/12/04 PHP
PHP中全局变量global和$GLOBALS[]的区别分析
2012/08/06 PHP
Laravel框架使用Seeder实现自动填充数据功能
2018/06/13 PHP
PHP 计算至少是其他数字两倍的最大数的实现代码
2020/05/26 PHP
asp.net+jquery滚动滚动条加载数据的下拉控件
2010/06/25 Javascript
基于jquery实现漂亮的动态信息提示效果
2011/08/02 Javascript
Three.js源码阅读笔记(光照部分)
2012/12/27 Javascript
动态显示可输入的字数提示还可以输入的字数
2014/04/01 Javascript
iframe窗口高度自适应的又一个巧妙实现思路
2014/04/04 Javascript
jquery显示隐藏input对象
2014/07/21 Javascript
JavaScript字符串对象split方法入门实例(用于把字符串分割成数组)
2014/10/16 Javascript
jQuery实现默认是闭合的FAQ展开效果菜单
2015/09/14 Javascript
js ajaxfileupload.js上传报错的解决方法
2016/05/05 Javascript
JavaScript实现复制或剪切内容到剪贴板功能的方法
2016/05/23 Javascript
Node.js connect ECONNREFUSED错误解决办法
2016/09/15 Javascript
详解IWinter 一个路由转控制器的 Nodejs 库
2017/11/15 NodeJs
Vue.directive使用注意(小结)
2018/08/31 Javascript
validform表单验证的实现方法
2019/03/08 Javascript
vue2.0自定义指令示例代码详解
2019/04/25 Javascript
Vue页面跳转传递参数及接收方式
2020/09/09 Javascript
js实现手表表盘时钟与圆周运动
2020/09/18 Javascript
Vue实现简单购物车功能
2020/12/13 Vue.js
[00:53]2015国际邀请赛 中国区预选赛一触即发
2015/05/14 DOTA
python监控nginx端口和进程状态
2019/09/06 Python
在Python中使用MongoEngine操作数据库教程实例
2019/12/03 Python
Python %r和%s区别代码实例解析
2020/04/03 Python
Python生成器next方法和send方法区别详解
2020/05/30 Python
浅谈keras中的keras.utils.to_categorical用法
2020/07/02 Python
Html5页面二次分享的实现
2018/07/30 HTML / CSS
Champs Sports加拿大:北美最大的以商场为基础的专业运动鞋和服装零售商之一
2018/05/01 全球购物
Hibernate持久层技术
2013/12/16 面试题
优秀的应届生自荐信
2014/05/23 职场文书
信息管理与信息系统专业求职信
2014/06/21 职场文书
公司开业主持词
2015/07/02 职场文书
幼儿园卫生保健制度
2015/08/05 职场文书
环保主题班会教案
2015/08/13 职场文书