zoukankan      html  css  js  c++  java
  • 用户注册与通知系统中观察者模式解析

    观察者模式

    是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。

    观察者设计模式可以解决哪些问题?

    观察者模式解决了以下问题:

    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()
  • 相关阅读:
    利用clear清除浮动的一些问题
    配置SpringBoot方便的切换jar和war
    java并发实战:连接池实现
    canvas绘制圆角头像
    对象的合并及拷贝
    JS数组去重
    浏览器端用JS实现创建和下载图片
    超过固定宽度(或行数)显示...(或省略)
    ssh实现免密登录
    Mac 日常使用问题收集
  • 原文地址:https://www.cnblogs.com/xueadas/p/9837011.html
Copyright © 2011-2022 走看看