python模式设计代码之观察者模式

news2024/9/23 12:34:05

1、观察者模式

话题订阅模式。观察者模式有两个角色,分别是话题发布者和话题订阅者(即观察者)。发布者就是把消息发送给话题,观察者就是订阅这个话题从而得到最新的资讯。这个模式的作用就拿手机的消息推送来说,app身为观察者提前订阅好话题,一旦发布者把信息发送给话题,所有的观察者就会收到这个信息。
在这里插入图片描述

2、观察者模式简单代码

定义发布者

class Subject:
    def __init__(self):
        self._observers = []

    def attach(self, observer):
        self._observers.append(observer)

    def detach(self, observer):
        self._observers.remove(observer)

    def notify(self,message):
        for observer in self._observers:
            observer.update(self, message)

定义观察者

class Observer:
    def update(self, subject,message):
        pass

class ConcreteObserverA(Observer):
    def update(self, subject,message):
        print("ConcreteObserverA: {message}")

class ConcreteObserverB(Observer):
    def update(self, subject,message):
        print("ConcreteObserverB: {message}")

使用观察者模式

# 创建主题对象
subject = Subject()

# 创建观察者对象
observer_a = ConcreteObserverA()
observer_b = ConcreteObserverB()

# 注册观察者到主题
subject.attach(observer_a)
subject.attach(observer_b)

# 模拟主题状态改变并通知观察者
subject.notify()

# 输出:
# ConcreteObserverA: Reacted to the event
# ConcreteObserverB: Reacted to the event

实际案例:和twisted联合运用

from twisted.internet.protocol import ReconnectingClientFactory, Protocol
from twisted.protocols.basic import LineReceiver
from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.internet import reactor
class Subject:
    """定义发布者"""
    def __init__(self):
        self._observers = []

    def attach(self, observer):
        self._observers.append(observer)

    def detach(self, observer):
        self._observers.remove(observer)

    def notify(self,message):
        for observer in self._observers:
            observer.update(self, message)
            
 class Observer:
     """定义观察者"""
    def update(self, subject,message):
        pass

class ConcreteObserverA(Observer):
    """观察者A"""
    def update(self, subject,message):
        print(f"观察到{message}")

class ConcreteObserverLog(Observer):
    def update(self, subject,message):
        print(f"{message}正在写入日志文件")
            
class  ClientProtocol(LineReceiver): 
    "客户端数据接受及处理模块"  
    #根据帧尾巴解决粘包 
    delimiter  = b'\x5F\x5F\x65\x6E\x64\x5F\x5F'

    def __init__(self):
        #开一个线程,可以不断接受客户端用户的输入、点击动作之类的,而不影响主线程
        reactor.callInThread(self.user_input)
        #初始化发布者,赋值给self.subject,用来发布信息用self.subject.notify(message)
        self.subject = Subject()
        #初始化观察者a和观察者b
        observer_a = ConcreteObserverA()
        observer_b = ConcreteObserverLog()
        #观察者a和观察者b订阅self.subject发布的话题,使用attach订阅
        self.subject.attach(observer_a)
        sself.ubject.attach(observer_b)
    def connectionLost(self, reason):
        print("Disconnected from the server!") 

    def lineReceived(self, line):
        #不断地接受服务端的信息;websocket、tcp协议等长连接会一直收到服务器信息
        #这里通过发布者subject.notify,不断地把新消息发布到话题上,这样每次有新消息
        #观察者的信息就会更新,并对应动作,比如写入日志文件、打印到终端
        self.subject.notify(line)
     def user_input(self):
         while True:
             the_input = input("请输入命令(输入'exit'退出): ")
             if command_key == 'EXIT':
                print("正在退出...")
                self.transport.loseConnection()
                break
 
 class ClientFactory(ReconnectingClientFactory):
    """Tcp 连接模块"""

    def startedConnecting(self, connector):
        print('Started to connect.')

    def buildProtocol(self, addr):
        print('Connected.')
        return ClientProtocol()

    def clientConnectionLost(self, connector, reason):
        print('Lost connection.  Reason:', reason)

    def clientConnectionFailed(self, connector, reason):
        print('Connection failed. Reason:', reason)
        ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)   
#运行起来twisted 
ClientInput = ClientFactory()
sender_endpoint = TCP4ClientEndpoint(reactor, "192.168.1.100", 9981)
sender_endpoint.connect(ClientInput)
reactor.run()       

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1996723.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入C# .NET核心:委托与事件机制全解析

摘要: 在C# .NET编程中,委托和事件是实现异步编程和对象间通信的关键机制。理解它们的工作原理对于编写高效、响应式的应用程序至关重要。本文将深入探讨C# .NET中的委托与事件,从基础概念到高级应用,为读者提供全面的指导。 正文…

如何提高游戏的可玩性和趣味性?

提高游戏的可玩性和趣味性是吸引玩家并保持他们长期参与的关键。以下是一些策略和建议,可以帮助您增强游戏的吸引力和娱乐价值: 1. 独特的游戏机制 创新玩法:开发新颖、独特的游戏机制,让玩家在体验中感受到前所未有的乐趣。避免…

【网络编程】字节序,IP地址、点分十进制、TCP与UDP的异同

记录学习,思维导图绘制 目录 1、字节序​编辑 2、IP地址 3、点分十进制 4、TCP与UDP的异同 1、字节序 2、IP地址 3、点分十进制 4、TCP与UDP的异同

STL源码刨析:红黑树(RB-tree)

目录 1.前言 2.RB-tree的简单介绍 3.RB-tree的插入节点操作 4.RB-tree的删除节点操作 5.RB-tree的节点设计 6.RB-tree的迭代器设计 7.RB-tree的数据结构 8.RB-tree的构造与内存管理 9.RB-treed的元素操作 前言 在文章《STL源码刨析:树的导览》中,曾简单的…

使用 MongoDB 构建 AI:Flagler Health 的 AI 旅程如何彻底改变患者护理

Flagler Health 致力于为慢性病患者提供支持,为其匹配合适的医生以提供合适的护理。 通常,身患严重病痛的患者面临的选择有限,他们往往需要长期服用阿片类药物,或寻求成本高昂的侵入性外科手术干预。遗憾的是,后一种方…

linux小组件:git

git是什么? git是版本控制器(去中心化的分布式系统)可以快速高效地处理从小型到大型的各种项目。易于学习,占地面积小,性能极快。它具有廉价的本地库,方便的暂存区域和多个工作流分支等特性。 什么叫版本…

【数据结构七夕专属版】单链表及单链表的实现【附源码和源码讲解】

本篇是博主在学习数据结构时的心得,希望能够帮助到大家,也许有些许遗漏,但博主已经尽了最大努力打破信息差,如果有遗漏还请见谅,嘻嘻,前路漫漫,我们一起前进!!&#xff0…

微信小程序--19(.wxml 模板文件简单归纳)

类似HTML用来描述当前页面的结构 一、普通样式 1.<view> 内容 </view> 二、滚波样式 1.<swiper> 内容 </swiper> 2.<swiper-item>滚波内容 </swiper-item> 3.常用属性 纵向&#xff1a;scroll-y横向&#xff1a;scroll-x圆点颜色&am…

LinuxC高级day03(Shell脚本)

【1】Shell脚本 1》Shell脚本基础概念 1> 概念 Shell使用方式&#xff1a;手动在命令行下命令或用Shell脚本 Shell脚本本质&#xff1a;Shell命令的有序集合 扩展名最好以 .sh 结尾&#xff0c;见名知义 也可以没有 Shell既是应用程序&#xff0c;又是一种脚本语言 解…

迁移学习之基本概念

迁移学习 1、通俗定义 迁移学习是一种学习的思想和模式 迁移学习作为机器学习的一个重要分支&#xff0c;侧重于将已经学习过的知识迁移应用于新的问题中 迁移学习的核心问题是&#xff0c;找到新问题和原问题之间的相似性&#xff0c;才可以顺利地实现知识地迁移 定义&…

运行pytorch报异常处理

一、问题现象及初步定位&#xff1a; 找不到指定的模块。 Error loading "D:\software\python3\Lib\site-packages\torch\lib\fbgemm.dll 此处缺少.dll文件&#xff0c;首先下载文件依赖分析工具 Dependencies https://github.com/lucasg/Dependencies/tree/v1.11.1 之后下…

leetcode169. 多数元素,摩尔投票法附证明

leetcode169. 多数元素 给定一个大小为 n 的数组 nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 示例 1&#xff1a; 输入&#xff1a;nums [3,2,3] 输…

C# winform 三层架构 增删改查 修改数据(修改篇)

ss一.留言 本专栏三层架构已经更新了 添加 登录 显示&#xff0c;还差修改以及删除&#xff0c;本篇更新修改&#xff0c;主要操作为点击修改某一条数据&#xff0c;然后跳转页面进行修改。 二.展示 我们先看DAL代码 /// <summary>/// 修改/// </summary>/// &l…

【RTOS面试题】什么是抢占?抢占的原理、抢占的好处、抢占有什么局限性?

&#x1f48c; 所属专栏&#xff1a;【RTOS-操作系统-面试题】 &#x1f600; 作  者&#xff1a; 于晓超 &#x1f680; 个人简介&#xff1a;嵌入式工程师&#xff0c;专注嵌入式领域基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大家&#xf…

大语言模型的模型量化(INT8/INT4)技术

目录 一、LLM.in8 的量化方案 1.1 模型量化的动机和原理1.2 LLM.int8 量化的精度和性能1.3 LLM.int8 量化的实践 二、SmoothQuant 量化方案 2.1 SmoothQuant 的基本原理2.2 SmoothQuant 的实践 三、GPTQ 量化训练方案 3.1 GPTQ 的基本原理3.2 GPTQ 的实践 参考资料 一、LLM.i…

让对话AI帮助你做程序架构设计,以及解决你的疑问

我想问下对话AI,本文采取的是chatgpt免费版 我问&#xff1a; 你说程序的设计&#xff0c;前后端分离的BS架构。比如工人基础档案1000条记录&#xff0c;工程项目基础档案10条记录&#xff0c;其他相关这两个基础档案的具体功能&#xff0c;比如打卡记录&#xff0c;宿舍记录&…

SD-WAN解决方案功能概述

SD-WAN&#xff08;软件定义广域网&#xff09;是一种前沿的网络技术&#xff0c;旨在为企业提供灵活、智能且高效的广域网连接。SD-WAN的主要功能可以分为四大类&#xff1a;路由、安全性、性能优化和管理控制。 路由功能 路由功能是SD-WAN解决方案的核心部分之一。传统的广域…

B站宋红康JAVA基础视频教程个人笔记chapter05

1.一维数组的定义方式 // 方式一(静态初始化) double[] prices; prices new double[]{20, 32, 43};// 方式二:&#xff08;动态初始化&#xff09; String[] foods; foods new String[4]; // 内部声明数组的长度 // String foods new String[4];// 其他方式 int[] prices …

【字符串哈希】

题目 代码 #include<bits/stdc.h> typedef unsigned long long ULL; const int N 1e510; const int P 131; char str[N]; ULL h[N], p[N]; ULL get_hash(int l, int r) {return h[r] - h[l-1] * p[r-l1]; } int n, m; int main() { scanf("%d%d", &n,…

Scrapy | 手动请求发送实现的数据爬取-段子王网站

文章目录 概要爬取流程代码技术细节format%回调函数 小结 概要 爬取段子王网站的标题和内容 核心 Scrapy的手动请求发送实现的数据爬取yield scrapy.Request(url,callback):GET-caL1back指宽解析函数&#xff0c;用于解析数据yield scrapy.ForRequest(url,callback,formdata):…