观察者模式
基本概念
它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
角色:
1、抽象主题(Subject):
它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
2、具体主题(Concrete Subject):
将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
3、抽象观察者(Observer):
为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
4、具体观察者(Concrete Observer):
实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调
过程
实现观察者模式有很多形式,比较直观的一种是使用一种“注册—通知—撤销注册”的形式。
观察者
(Observer)将自己注册到被观察对象(Subject)中,被观察对象将观察者存放在一个容器(Container)里。
被观察
被观察对象发生了某种变化(如图中的SomeChange),从容器中得到所有注册过的观察者,将变化通知观察者。
撤销观察
观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。
UML类图:
例子一:女神与舔狗
舔狗想知道女神都在干些什么,那么首先舔狗得观察女神,然后女神得允许接受舔狗的观察。
class Observer(abc.ABC): def __init__(self, subject): self.subject = subject # 目标对象 @abc.abstractmethod def update(self): pass class TIMDog(Observer): def __init__(self,subject): super().__init__(subject) def update(self): print("舔狗看到女神正在:") print(self.subject.word) class Woman: def __init__(self): self.observer = [] @property def word(self): if hasattr(self, '_word'): return self._word return None @word.setter def word(self, value): self._word = value self.message() def attach(self, observer: Observer): # 依赖倒置原则 self.observer.append(observer) def remove(self, observer): self.observer.remove(observer) def message(self): for obs in self.observer: obs.update() w = Woman() t = TIMDog(w) # 我要观察W w.attach(t) # w 授权 允许 t 观察 w.word = "自摸 幺鸡"
例子二:采用 __call__ 可调用对象来实现
什么是可调用对象?
一个类只要实现了__call__魔术方法, 就表示当前对象实例可用函数那么调用。
可调用对象有:函数 与实现__call__的类对象实例
class Obj: def __call__(self): pass o = Obj() # 可调用对象 也就是说 对象实例可以用方法那样 o() 等价于 o.__call__()
采用__call__改版后的观察者模式
import abc from typing import List ''' 舔狗想知道女神都在干些什么,那么首先舔狗得观察女神,然后女神得允许接受舔狗的观察。 ''' class Observer(abc.ABC): def __init__(self, subject): self.subject = subject # 目标对象 @abc.abstractmethod def __call__(self): pass class TIMDog(Observer): def __init__(self,subject): super().__init__(subject) def __call__(self): print("舔狗看到女神正在:") print(self.subject.word) class Woman: def __init__(self): self.observer = [] @property def word(self): if hasattr(self, '_word'): return self._word return None @word.setter def word(self, value): self._word = value self.message() def attach(self, observer: Observer): self.observer.append(observer) def remove(self, observer): self.observer.remove(observer) def message(self): for obs in self.observer: obs() w = Woman() t = TIMDog(w) # 我要观察W w.attach(t) # w 授权 允许 t 观察 w.word = "自摸 幺鸡"