• 设计模式Python实现-观察者模式


    观察者模式(发布-订阅模式 Publish Subscribe Pattern):定义了一种一对多的关系,让多个观察对象同时监听一个主题对象,当主题对象状态发生变化时会通知所有观察者,是它们能够自动更新自己,是一种行为设计模式。

    观察者模式的结构

    1,Publisher 会向其他对象发送值得关注的事件notifySubscribers。事件会在发布者自身状态改变或执行特定行为后发生。发布者中包含一个允许新订阅者加入subscribe和当前订阅者离开列表unsubscribe的订阅构架。

    2,当新事件发生时,发送者会遍历订阅列表并调用每个订阅者对象的通知方法。该方法是在订阅者接口中声明的。

    3,Subscriber 接口声明了通知接口。在绝大多数情况下,该接口仅包含一个update方法。该方法可以拥有多个参数,使发布者能在更新时传递事件的详细信息。

    4,Concrete Subscriber 具体订阅者,可以执行一些操作来回应发布者的通知。所有具体订阅者类都实现了同样的接口,发布者不与具体类相耦合。

    5,订阅者通常需要一些上下文信息来正确地处理更新。因此,发布者通常会将一些上下文数据作为通知方法的参数进行传递。发布者也可将自身作为参数进行传递,使订阅者直接获取所需的数据。

    6,Client 会分别创建发布者和订阅者对象,然后为订阅者注册发布者更新。

    观察者代码

      1 from __future__ import annotations
      2 from abc import ABC, abstractmethod
      3 from random import randrange
      4 from typing import List
      5 
      6 
      7 class Subject(ABC):
      8     """
      9     声明一组用于管理订阅者的方法
     10     """
     11 
     12     @abstractmethod
     13     def attach(self, observer: Observer) -> None:
     14         """
     15         添加观察者到subject.
     16         """
     17         pass
     18 
     19     @abstractmethod
     20     def detach(self, observer: Observer) -> None:
     21         """
     22         从subject删除观察者.
     23         """
     24         pass
     25 
     26     @abstractmethod
     27     def notify(self) -> None:
     28         """
     29         通知观察者事件的发生.
     30         """
     31         pass
     32 
     33 
     34 class ConcreteSubject(Subject):
     35     """
     36     Subject有一些状态,状态变更需要通知观察者
     37     """
     38     # Subject的状态,所有的订阅者都要有,
     39     _state: int = None
     40 
     41     # 订阅用户列表
     42     _observers: List[Observer] = []
     43 
     44     def attach(self, observer: Observer) -> None:
     45         print("Subject: Attached an observer.")
     46         self._observers.append(observer)
     47 
     48     def detach(self, observer: Observer) -> None:
     49         self._observers.remove(observer)
     50 
     51     # 通知所有订阅者
     52     def notify(self) -> None:
     53         """
     54         通知接口,触发了所有的订阅用户的update方法
     55         """
     56 
     57         print("Subject: Notifying observers...")
     58         for observer in self._observers:
     59             observer.update(self)
     60 
     61     def some_business_logic(self) -> None:
     62         """
     63         一些业务逻辑块,处理业务逻辑后,也可能会触发状态的变更,需要调用notify通知所有订阅者,
     64         """
     65 
     66         print("
    Subject: state change")
     67         self._state = randrange(0, 10)
     68 
     69         print(f"Subject: My state has changed to: {self._state}")
     70         self.notify()
     71 
     72 
     73 class Observer(ABC):
     74     """
     75     订阅者声明对象使用的update.
     76     """
     77 
     78     @abstractmethod
     79     def update(self, subject: Subject) -> None:
     80         """
     81         接收到状态变更.
     82         """
     83         pass
     84 
     85 
     86 """
     87 具体订阅者,对状态的变更做出具体反应
     88 """
     89 
     90 
     91 class ConcreteObserverA(Observer):
     92     def update(self, subject: Subject) -> None:
     93         if subject._state < 3:
     94             print("ConcreteObserverA: Reacted to the event")
     95 
     96 
     97 class ConcreteObserverB(Observer):
     98     def update(self, subject: Subject) -> None:
     99         if subject._state == 0 or subject._state >= 2:
    100             print("ConcreteObserverB: Reacted to the event")
    101 
    102 
    103 if __name__ == "__main__":
    104     # The client code.
    105 
    106     subject = ConcreteSubject()
    107 
    108     observer_a = ConcreteObserverA()
    109     subject.attach(observer_a)
    110 
    111     observer_b = ConcreteObserverB()
    112     subject.attach(observer_b)
    113 
    114     subject.some_business_logic()
    115     subject.some_business_logic()
    116 
    117     subject.detach(observer_a)
    118 
    119     subject.some_business_logic()

    适用场景:

    1,当一个对象状态的改变需要改变其他对象,或实际对象是事先未知的或动态变化的时,可使用观察者模式。

    2,当应用中的一些对象必须观察其他对象时,可使用该模式。

    优点:

    符合开闭原则,不用修改发布者代码就能引入新的订阅者类。

    可以在运行时建立对象之间的联系。

    缺点:

    订阅者的通知顺序是随机的


    作者:Andy
    出处:http://www.cnblogs.com/onepiece-andy/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    asp.net获取当前页面的url地址
    取多个name值相同的input里面的值
    多线程实践
    《谷物大脑》是骗子写的伪科学书:樊登著作4本,都是3星
    历史远未终结,全球化面临挑战:4星|《世界不是平的》
    大众汽车的恐吓文化导致了排放门:4星|《像职场赢家一样做减法》
    穿越回秦朝能发电吗?能:4星|《1分钟物理》
    作者没有实战经验,案例老旧,图表水平差:2星|《社群思维》
    滴滴优步面临各地竞争对手难以通吃:4星|《哈佛商业评论》第3期
    2星|《重新定义物流》:形式像PPT,内容像公关稿
  • 原文地址:https://www.cnblogs.com/onepiece-andy/p/python-publish-subscribe-pattern.html
Copyright © 2020-2023  润新知