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处理圆角图片、圆形图片的例子
Apr 25 Python
python基础教程之面向对象的一些概念
Aug 29 Python
python smtplib模块发送SSL/TLS安全邮件实例
Apr 08 Python
python实现将pvr格式转换成pvr.ccz的方法
Apr 28 Python
python之消除前缀重命名的方法
Oct 21 Python
python 重命名轴索引的方法
Nov 10 Python
Django框架登录加上验证码校验实现验证功能示例
May 23 Python
python二元表达式用法
Dec 04 Python
python GUI库图形界面开发之PyQt5信号与槽的高级使用技巧装饰器信号与槽详细使用方法与实例
Mar 06 Python
python使用PIL剪切和拼接图片
Mar 23 Python
Python使用sys.exc_info()方法获取异常信息
Jul 23 Python
Python requests库参数提交的注意事项总结
Mar 29 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读取RSS(Feed)简单实例
2014/06/12 PHP
让ThinkPHP的模板引擎达到最佳效率的方法详解
2017/03/14 PHP
PHP封装的mysqli数据库操作类示例
2019/02/16 PHP
YII2框架中behavior行为的理解与使用方法示例
2020/03/13 PHP
基于php伪静态的实现方法解析
2020/07/31 PHP
HR vs ForZe BO3 第二场 2.13
2021/03/10 DOTA
javascript 图片上一张下一张链接效果代码
2010/03/12 Javascript
动态加载js的方法汇总
2015/02/13 Javascript
localResizeIMG先压缩后使用ajax无刷新上传(移动端)
2015/08/11 Javascript
JS组件Bootstrap Table使用方法详解
2016/02/02 Javascript
AngularJS使用ng-repeat指令实现下拉框
2016/08/23 Javascript
Vue.js实现拖放效果的实例
2016/09/30 Javascript
jquery插件bootstrapValidator表单验证详解
2016/12/15 Javascript
Jquery Easyui对话框组件Dialog使用详解(14)
2016/12/19 Javascript
js实现3D图片展示效果
2017/03/09 Javascript
vue构建单页面应用实战
2017/04/10 Javascript
详解nodejs实现本地上传图片并预览功能(express4.0+)
2017/06/28 NodeJs
微信小程序开发之animation循环动画实现的让云朵飘效果
2017/07/14 Javascript
React中this丢失的四种解决方法
2019/03/12 Javascript
修改Vue打包后的默认文件名操作
2020/08/12 Javascript
Vue自定义组件双向绑定实现原理及方法详解
2020/09/03 Javascript
Vue如何循环提取对象数组中的值
2020/11/18 Vue.js
介绍Python的Urllib库的一些高级用法
2015/04/30 Python
Python 编码处理-str与Unicode的区别
2016/09/06 Python
python如何实现从视频中提取每秒图片
2020/10/22 Python
pytorch 改变tensor尺寸的实现
2020/01/03 Python
Python运行异常管理解决方案
2020/03/09 Python
ECCO俄罗斯官网:北欧丹麦鞋履及皮具品牌
2020/06/26 全球购物
中学生班主任评语
2014/01/30 职场文书
资源工程专业毕业生求职信
2014/02/27 职场文书
《锄禾》教学反思
2014/04/08 职场文书
服务标语大全
2014/06/18 职场文书
小学数学国培研修日志
2015/11/13 职场文书
反四风问题学习心得体会
2016/01/22 职场文书
幼儿园教学反思范文
2016/03/02 职场文书
工程移交协议书
2016/03/24 职场文书