单个对此(发布者,也称为主体或是可观察对象)和一个或是多个对象(订阅者,也称为观察者)之间的发布-订阅关系。增加发布者和订阅这个之间解耦,使得在运行时添加、删除订阅者变得容易。对于MVC, 发布者是模型,订阅者是视图。
拍卖场景:
每个竞买人,都有一个号码牌,当天安门想要出价时,就举起号码牌。当竞买人举起牌子时,拍卖人即为主体,更新竞买价格,并将新价格广播给所有竞买人(竞买者)。
软件场景:
RabbitMQ 库可以用于应用程序添加异步消息支持,支持多种消息协议,http和amqp 。RbbitMQ 可以在Python 应用与发布订阅模式,该模式就是观察者设计模式。
新闻流:
使用RSS 、Atom 或其他相关格式。可以关注一个新闻流,每次更新时候,你都会收到一个关于更新的通知。
事件驱动系统
监听器监听特定的事件,监听器在监听的事件被创建时触发。这个事件可以是按下一个特定的键,移动鼠标,事件扮演发布者的角色,监听器扮演观察者的角色。可以为单个事件(发布者)添加多个监听器(观察者)。
案例格式化程序,有一个默认的格式化程序,以十进制格式显示一个值,可以添加、注册更多的格式化程序。每次更新默认的格式化程序时候,都会通知已经注册的格式化程序采取行动。程序以相关格式显示新的值。
(1) 定义 Publisher 类。
(2) 定义 DefaultFormatter 类,以及特殊的 __init__ 和 __str__ 方法。
(3) 向 DefaultFormatter 类添加 data 属性的设置方法和获取方法。
(4) 定义两个观察者类
(5) 添加程序的主体部分。 main() 函数的第一部分如下。
class Publisher: def __init__(self): self.observers = [] # 保存观察者 def add(self, observer): if observer not in self.observers: self.observers.append(observer) else: print(f'Failed to add:{observer}') def remove(self, observer): try: self.observers.remove(observer) except ValueError: print(f"Failed to remove:{observer}") def notify(self): print("所有观察者通知更新") [o.notify(self) for o in self.observers] class DefaultFormatter(Publisher): def __init__(self, name): Publisher.__init__(self) self.name = name self._data = 0 def __str__(self): return f"{type(self).__name__}:'{self.name}' has data ={self._data}"@property def data(self): return self._data @data.setter def data(self, new_value): try: self._data = int(new_value) except ValueError as e: print(f"Error:{e}") else: self.notify() # 执行通知"""定义两个观察者"""class HexFormatterObs: def notify(self, publisher): value = hex(publisher.data) print(f"{type(self).__name__}: '{publisher.data}' has now hex data ={value}") class BinaryFormatterObs: def notify(self, publisher): value = bin(publisher.data) print(f"{type(self).__name__}:'{publisher.data}' has now bin data ={value}") def main(): df=DefaultFormatter('test1') print(df) print("---------------------") hf=HexFormatterObs() df.add(hf) df.data=3 print(df) bf=BinaryFormatterObs() df.add(bf) df.data=21 print(df) print("----------hello-----------") df.data='hello' print(df) print("----------15.8-----------") df.data=15.8 print(df) if __name__ == '__main__': main() # try: # print("33333") # except: # print("wwww") # else: # print("else")执行结果
DefaultFormatter:'test1' has data =0 --------------------- 所有观察者通知更新 HexFormatterObs: '3' has now hex data =0x3 DefaultFormatter:'test1' has data =3 所有观察者通知更新 HexFormatterObs: '21' has now hex data =0x15 BinaryFormatterObs:'21' has now bin data =0b10101 DefaultFormatter:'test1' has data =21 ----------hello----------- Error:invalid literal for int() with base 10: 'hello' DefaultFormatter:'test1' has data =21 ----------15.8----------- 所有观察者通知更新 HexFormatterObs: '15' has now hex data =0xf BinaryFormatterObs:'15' has now bin data =0b1111 DefaultFormatter:'test1' has data =15