觀察者模式 -- 女神與舔狗例子

基本概念

它定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知並被自動更新。

角色:
一、抽象主題(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 = "自摸 幺雞"
相關文章
相關標籤/搜索