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

基本概念

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

角色:
一、抽象主题(Subject):
它把全部观察者对象的引用保存到一个汇集里,每一个主题均可以有任何数量的观察者。抽象主题提供一个接口,能够增长和删除观察者对象。
二、具体主题(Concrete Subject):
将有关状态存入具体观察者对象;在具体主题内部状态改变时,给全部登记过的观察者发出通知。
三、抽象观察者(Observer):
为全部的具体观察者定义一个接口,在获得主题通知时更新本身。
四、具体观察者(Concrete Observer):
实现抽象观察者角色所要求的更新接口,以便使自己的状态与主题状态协调

过程
实现观察者模式有不少形式,比较直观的一种是使用一种“注册—通知—撤销注册”的形式。
观察者
(Observer)将本身注册到被观察对象(Subject)中,被观察对象将观察者存放在一个容器(Container)里。
被观察
被观察对象发生了某种变化(如图中的SomeChange),从容器中获得全部注册过的观察者,将变化通知观察者。
撤销观察
观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。

app

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__魔术方法, 就表示当前对象实例可用函数那么调用。spa

可调用对象有:函数 与实现__call__的类对象实例code

class Obj:
    def __call__(self):
        pass

o = Obj()


# 可调用对象 也就是说 对象实例能够用方法那样
o() 等价于 o.__call__() 

 

采用__call__改版后的观察者模式server

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 = "自摸 幺鸡"
相关文章
相关标签/搜索