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

1、观察者模式

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

2、观察者模式简单代码

定义发布者

python 复制代码
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)

定义观察者

python 复制代码
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}")

使用观察者模式

python 复制代码
# 创建主题对象
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联合运用

python 复制代码
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()       
相关推荐
小徐不徐说13 小时前
序列化与反序列化:把 C++ 对象可靠地保存下来
开发语言·数据库·c++·php
ragnwang14 小时前
Notes: Python pybind11 import C++ module
开发语言·c++·python
王中阳Go14 小时前
后端转 Agent 岗面试怎么答:8 个高频问题与应答口径
人工智能·后端·python·大语言模型
Wang's Blog14 小时前
Java 项目实战: 交友项目 - 搜索附近的功能概述和分析
java·开发语言·交友
骑着蜗牛撵大象32714 小时前
大模型 Agent 的沙箱护栏:gVisor 隔离、出口白名单与审计闭环
java·开发语言·jvm·安全·agent沙箱·gvisor·microvm
weixin_3077791314 小时前
RAG 面试陷阱——混合检索并非无条件优越:一个条件反转实验
人工智能·python·面试·职场和发展
Dxy123931021615 小时前
JS DES 加密详解
开发语言·javascript·arcgis
充值内卷15 小时前
我给桌面加了个鱼缸:C++ 写后端,WebView2 里养一座 Three.js 小岛
开发语言·javascript·c++
云和数据.ChenGuang15 小时前
深入解析 Python 的 dir():从用法到 CPython 源码实现
开发语言·人工智能·python·langchain
nice_lcj52016 小时前
深入理解 Java 反射:从 Class 对象到方法调用(含性能实测 + 迷你 IOC 实战 + 面试考点)
java·开发语言·后端·面试