观察者模式 -- 女神与舔狗例子

基本概念

它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

角色:
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 = "自摸 幺鸡"

猜你喜欢

转载自www.cnblogs.com/whnba/p/11871542.html