设计模式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("\nSubject: 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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 

posted @ 2017-11-13 15:34  Andy冉明  阅读(627)  评论(0编辑  收藏  举报