观察者模式
是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。
观察者设计模式可以解决哪些问题?
观察者模式解决了以下问题:
1对象之间的一对多依赖关系应该在不使对象紧密耦合的情况下定义。
2应该确保当一个对象改变状态时,会自动更新无限数量的依赖对象。
3一个对象可以通知无限数量的其他对象,这应该是可能的。
通过定义一个直接更新依赖对象状态的对象(主题)来定义对象之间的一对多依赖关系是不灵活的,因为它将主题提交(紧密耦合)到特定的依赖对象。紧密耦合的对象很难实现、更改、测试和重用,因为它们引用和了解(如何更新)许多具有不同接口的不同对象。
观察者设计模式描述了什么解决方案?
定义主题和观察者对象。
这样,当一个主题改变状态时,所有注册的观察者都会被自动通知和更新。
主题的唯一责任是维护一个观察者列表,并通过调用其update()操作来通知他们状态更改。
观察者的职责是在一个主题上注册(和注销)自己(获得状态变化的通知),并在被通知时更新他们的状态(使他们的状态与主题的状态同步)。
这使得主题和观察者松散耦合。主体和观察者对彼此没有明确的了解。可以在运行时独立地添加和删除观察者。
这种通知注册交互也称为发布-订阅。
请参阅下面的UML类和序列图。
耦合和典型的发布-订阅实现
通常情况下,观察者模式实现的“主题”(这是“观察”)的观察对象的状态变化,传达到观察者发生。 这种类型的实施被认为是“ 紧耦合的 ”,迫使观察员和主题意识到彼此,可以访问他们的内部零件,创造可能的问题 可伸缩性 、速度、信息恢复和维护(也称为事件或通知损失),有条件的缺乏灵活性分散所需的安全措施和可能的阻碍。 在某些( non-polling )的实现 发布-订阅模式 (也称为发布—订阅模式)中,这是通过创建一个专门的“消息队列”服务器来解决,有时一个额外的“消息处理程序”对象,随着添加阶段之间的观察者和观察到的对象的状态检查,因此“脱钩”的软件组件。 在这些情况下,消息队列服务器访问的观察家观察者模式,“订阅某些消息“知道只有预期的消息(不信,在某些情况下),但对消息发送者本身一无所知,接收方和发送方可能一无所知。 其他发布-订阅模式的实现,这些实现类似效果的通知和沟通感兴趣,完全不使用观察者模式。
在早期实现多窗口操作系统OS2和窗户,术语“发布-订阅模式”和“事件驱动软件开发”作为观察者模式的同义词。
实现
观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。
ObserverPatternDemo,我们的演示类使用 Subject 和实体类对象来演示观察者模式。
观察者模型分析:
https://github.com/surjitr/ObserverPattern
这是一个用于注册和通知观察者任何事件的观察者模式示例
#这是观察者可以注册的可观察类
class Observable: #创建观察者类 def __init__(self): self.observers=[] #用于观察者注册 def register(self, observer): if not observer in self.observers: self.observers.append(observer) print("Observer %s registered" % observer) #用于观察者注销 def unregister(self, observer): if observer in self.observers: self.observer.remove(observer) print("Observer %s removed" % observer) #注销所有观察者 def unregister_all(self): del self.observers[:] print("Unregistered all observers") #观察者更新 def update_observers(self, * args, **kwargs): for observer in self.observers: observer.update(*args, **kwargs)
#检测观察者模式应用程序 from Observable import Observable from observerbase import BaseClass class ObserverA(BaseClass): #定义观察者A类 def __init__(self): #观察者A的构造函数 def update(self, *args, **kwargs): #当被调用时更新参数 print("ObserverA update invoked") for arg in args: print(arg) for key,value in kwargs.items(): print(key,":",value) class ObserverB(BaseClass): #定义观察者B类 def __init__(self): #观察者B的构造函数 def update(self, *args, **kwargs): #当被调用时更新参数 print("ObserverB update invoked") for arg in args: print(arg) for key,value in kwargs.items(): print(key,":",value) if __name__ == "__main__": underObservation = Observable() bot1 = ObserverA() bot2 = ObserverB() underObservation.register(bot1) underObservation.register(bot2) underObservation.update_observers(('SMA indicates SELL', 'Bollinger Resistance', 'SELL'), {"Lotsize": 37, "TakeProfit": 300, "SL": 50})
#观察者的抽象基类 from abc import ABCMeta, abstractmethod class BaseClass(metaclass=ABCMeta): #用于创建观察者的基类 def update(self, *args, **kwargs): pass # no need to define here. will handle in derived
#观察者模式的单元测试
import unittest
from Observable import Observable
from observerbase import BaseClass
class TestObserver(BaseClass):
def __init__(self):
args = []
kwargs = {}
def update(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
return
class UnitTestObserver(unittest.TestCase):
#定义测试类
def setUp(self):
self.undOb = Observable()
self.bot1 = TestObserver()
self.bot2 = TestObserver()
def tearDown(self):
del self.undOb
del self.bot1
del self.bot2
#观察者列表非空
def test_defaultNoObserver(self):
self.assertEqual(len(self.undOb.observers),0," Observer list is not empty")
#重复观察者注册
def test_DuplicateObservers(self):
self.undOb.register(self.bot1)
self.undOb.register(self.bot2)
self.undOb.register(self.bot1)
self.assertEqual(len(self.undOb.observers),2,"Duplicate observers registered")
#移除所有观察者
def test_RemoveAllSubscribers(self):
self.undOb.register(self.bot1)
self.undOb.register(self.bot2)
self.undOb.register(self.bot1)
self.undOb.unregister_all()
self.assertEqual(len(self.undOb.observers), 0, "Observers still registered")
if __name__ == "__main__":
unittest.main()