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 相关文章推荐
跟老齐学Python之使用Python操作数据库(1)
Nov 25 Python
在RedHat系Linux上部署Python的Celery框架的教程
Apr 07 Python
Python实现的数据结构与算法之快速排序详解
Apr 22 Python
Python实现Windows上气泡提醒效果的方法
Jun 03 Python
Python实现基本线性数据结构
Aug 22 Python
python多进程实现进程间通信实例
Nov 24 Python
利用Python如何实现数据驱动的接口自动化测试
May 11 Python
在Python文件中指定Python解释器的方法
Feb 18 Python
Python实现打印实心和空心菱形
Nov 23 Python
python GUI库图形界面开发之PyQt5打开保存对话框QFileDialog详细使用方法与实例
Feb 27 Python
python 读取串口数据的示例
Nov 09 Python
使用Python快速打开一个百万行级别的超大Excel文件的方法
Mar 02 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中直接导入svn中的项目的方法步骤
2013/06/21 PHP
thinkphp中session和cookie无效的解决方法
2014/12/19 PHP
PHP中filter函数校验数据的方法详解
2015/07/31 PHP
xml文档转换工具,附图表例子(hta)
2010/11/17 Javascript
js拦截alert对话框另类应用
2013/01/16 Javascript
js substring从右边获取指定长度字符串(示例代码)
2013/12/23 Javascript
js实现局部页面打印预览原理及示例代码
2014/07/03 Javascript
jQuery简单tab切换效果实现方法
2015/04/08 Javascript
javascript图片滑动效果实现
2021/01/28 Javascript
jQuery无缝轮播图代码
2016/12/22 Javascript
vue中v-for加载本地静态图片方法
2018/03/03 Javascript
AngularJS中重新加载当前路由页面的方法
2018/03/09 Javascript
vue src动态加载请求获取图片的方法
2018/10/17 Javascript
js计算两个时间差 天 时 分 秒 毫秒的代码
2019/05/21 Javascript
微信小程序开发技巧汇总
2019/07/15 Javascript
Python  连接字符串(join %)
2008/09/06 Python
详解Django 中是否使用时区的区别
2018/06/14 Python
django将数组传递给前台模板的方法
2019/08/06 Python
Jupyter notebook设置背景主题,字体大小及自动补全代码的操作
2020/04/13 Python
Python run()函数和start()函数的比较和差别介绍
2020/05/03 Python
keras绘制acc和loss曲线图实例
2020/06/15 Python
Python 爬虫批量爬取网页图片保存到本地的实现代码
2020/12/24 Python
CSS3.0实现霓虹灯按钮动画特效的示例代码
2021/01/12 HTML / CSS
详解移动端Html5页面中1px边框的几种解决方法
2018/07/24 HTML / CSS
Jacadi Paris英国官网:法国童装品牌
2019/08/09 全球购物
应届生求职推荐信
2013/10/28 职场文书
研究生自我鉴定范文
2013/10/30 职场文书
亚运会口号
2014/06/20 职场文书
2014统计局民主生活会对照检查材料思想汇报
2014/10/02 职场文书
2015年教务处干事工作总结
2015/07/22 职场文书
同事离别感言
2015/08/04 职场文书
奖学金发言稿(范文)
2019/08/21 职场文书
对Golang中的FORM相关字段理解
2021/05/02 Golang
使用Redis实现秒杀功能的简单方法
2021/05/08 Redis
如何优化vue打包文件过大
2022/04/13 Vue.js
华为HarmonyOS3.0强在哪? 看看鸿蒙3.0这7个小功能
2023/01/09 数码科技