观察者模式
定义:观察者模式又叫做发布-订阅(Publish-Subscribe)模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
角色
- 抽象主题(Subject)
- 具体主题(ConcreteSubject)-- 发布者
- 抽象观察者(Observer)
- 具体观察者(ConcreteObserver)-- 订阅者
适用场景
- 当一个抽象模型有两方面,其中一个方面依赖于另一个方面。将这两者封装在独立对象中以使它们可以各自独立地改变和复用;
- 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变;
- 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的;
优点
- 目标和观察者之间的抽象耦合最小
- 支持广播
大家可以想想微博中是否就采用了这种设计模式,在我们关注某个博主后,一旦该博主有新的内容更新时,我们就会收到订阅通知。
抽象主题:提供接口,可以增加和删除观察者对象,通知消息;
具体主题:即发布者,将有关状态存入具体观察者对象,在具体主题的内部状态发生变化时,给所有登记过的观察者发出通知;
抽象观察者:定义接口,在得到主题的通知时更新自己;
具体观察者:即订阅者,实现更新接口,以使本身的状态与主题状态一致;
应用案例
在公司里面,如果有集体通知消息时,所有员工都会收到;下面通过观察者模式来进行简单实现;
from abc import ABCMeta, abstractmethod
# 抽象订阅者
class Observer(metaclass=ABCMeta):
@abstractmethod
def update(self, notice): # notice是一个Notice类的对象
pass
# 抽象发布者
class Notice:
def __init__(self):
self.observers = []
def attach(self, obs):
# 添加订阅者
self.observers.append(obs)
def detach(self, obs):
# 删除订阅者
self.observers.remove(obs)
def notify(self):
# 通知所有的订阅者
for obs in self.observers:
obs.update(self)
# 具体发布者
class StaffNotice(Notice):
def __init__(self, name: str, company_info: str = None):
super(StaffNotice, self).__init__()
self.name = name
self.__company_info = company_info
@property
def company_info(self):
return self.__company_info
@company_info.setter
def company_info(self, info):
self.__company_info = info
# 发布新消息并通知所有的订阅者
self.notify()
class Staff(Observer):
def __init__(self, name: str):
self.name = name
def update(self, notice: StaffNotice):
print("{}收到{}通知,{}".format(self.name, notice.name, notice.company_info))
def main():
notice = StaffNotice("人事", "初始公司消息")
s1 = Staff("1号员工")
notice.attach(s1)
s2 = Staff("2号员工")
notice.attach(s2)
notice.company_info = "最新消息:公司今年业绩非常好,给大家准备了丰厚的奖金!"
notice.detach(s2)
notice.company_info = "最新消息:中秋和国庆放假8天"
if __name__ == '__main__':
main()
参考资料
《大话设计模式》