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()