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实现哈希表
Feb 07 Python
Python3基础之输入和输出实例分析
Aug 18 Python
Python深入学习之闭包
Aug 31 Python
python实现可以断点续传和并发的ftp程序
Sep 13 Python
Python3.6正式版新特性预览
Dec 15 Python
关于python的bottle框架跨域请求报错问题的处理方法
Mar 19 Python
PyQt5主窗口动态加载Widget实例代码
Feb 07 Python
python实现对求解最长回文子串的动态规划算法
Jun 02 Python
Python处理时间日期坐标轴过程详解
Jun 25 Python
python GUI库图形界面开发之PyQt5简单绘图板实例与代码分析
Mar 08 Python
python实现人像动漫化的示例代码
May 17 Python
keras load model时出现Missing Layer错误的解决方式
Jun 11 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
php json与xml序列化/反序列化
2013/10/28 PHP
php 删除指定文件夹的实例讲解
2017/07/25 PHP
PHP实现数组的笛卡尔积运算示例
2017/12/15 PHP
使用jQuery+HttpHandler+xml模拟一个三级联动的例子
2011/08/09 Javascript
Fastest way to build an HTML string(拼装html字符串的最快方法)
2011/08/20 Javascript
js的匿名函数使用介绍
2013/12/11 Javascript
js特殊字符过滤的示例代码
2014/03/05 Javascript
jquery插件开发之实现jquery手风琴功能分享
2014/03/10 Javascript
jquery自适应布局的简单实例
2016/05/28 Javascript
浅谈箭头函数写法在ReactJs中的使用
2017/08/22 Javascript
使用JavaScript实现一个小程序之99乘法表
2017/09/21 Javascript
基于javascript中的typeof和类型判断(详解)
2017/10/27 Javascript
如何为你的JavaScript代码日志着色详解
2019/04/08 Javascript
Angular8 Http拦截器简单使用教程
2019/08/20 Javascript
vue+animation实现翻页动画
2020/06/29 Javascript
vue使用lodop打印控件实现浏览器兼容打印的方法
2021/02/07 Vue.js
python实现颜色空间转换程序(Tkinter)
2015/12/31 Python
使用Python+Splinter自动刷新抢12306火车票
2018/01/03 Python
Python基于pyCUDA实现GPU加速并行计算功能入门教程
2018/06/19 Python
python从子线程中获得返回值的方法
2019/01/30 Python
将python文件打包成EXE应用程序的方法
2019/05/22 Python
我就是这样学习Python中的列表
2019/06/02 Python
win10下安装Anaconda的教程(python环境+jupyter_notebook)
2019/10/23 Python
Python的形参和实参使用方式
2019/12/24 Python
Python3爬虫里关于代理的设置总结
2020/07/30 Python
使用scrapy ImagesPipeline爬取图片资源的示例代码
2020/09/28 Python
calendar在python3时间中常用函数举例详解
2020/11/18 Python
Canvas高级路径操作之拖拽对象的实现
2019/08/05 HTML / CSS
xml有哪些解析技术?区别是什么
2016/04/26 面试题
函数只定义了一次, 调用了一次, 但编译器提示非法重定义了-什么问题?
2014/10/03 面试题
进修护士自我鉴定
2013/10/14 职场文书
会计职业生涯规划书
2014/01/13 职场文书
营销总经理岗位职责
2014/02/02 职场文书
名人演讲稿范文
2014/09/16 职场文书
SpringBoot集成Redis,并自定义对象序列化操作
2021/06/22 Java/Android
pd.DataFrame中的几种索引变换的实现
2022/06/16 Python