红帽家 记录技术与生活

设计模式

观察者模式

观察者模式(Observer Pattern)是一种行为型设计模式,被设计为一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新

依赖对象:观察者对象

如何解决:试用面向对象技术,可以将这种依赖关系弱化 关键代码:在抽象类里有一个ArrayList存放观察者们

优点:

  1. 观察者和被观察者都是抽象耦合的
  2. 建立一套触发机制

缺点:

  1. 如果被一个被观察者有很多直接或间接观察者,通知所有的观察者会花费很多时间
  2. 如果观察者和被观察者间有互相依赖,会触发他们之间的循环依赖,可能会导致系统崩溃
  3. 观察者模式不能让观察者得知被观察者是如何发生变化的,仅仅是知道观察者目标发生了变化。

注意事项:

  1. JAVA中已经有了对观察者模式的支持类
  2. 避免循环引用
  3. 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式

核心角色:

  1. 主题(Subjuect):被观察者,具有状态的对象,并维护观察者列表,包含添加、删除、通知观察者的方法。
  2. 观察者(Observer):接收主题通知的对象。需要更新方法,当接收到主题通知时,调用此方法进行更新操作。
  3. 具体主题(Concrete Subject):主题的具体实现类,维护观察者列表,并在状态发生变化时通知观察者。
  4. 具体观察者(Concrete Observer):观察者的具体实现类,实现更新方法。

具体实现,包含三个类:Subjuct类、Observer类、Client类 ![[设计模式-观察者模式类架构.png]]

from __future__ import annotations
from abc import ABC, abstractmethod
from random import randrange
from typing import List

class Subject(ABC):
    """
    The Subject interface declares a set of methods for managing subscribers.
    """

    @abstractmethod
    def attach(self, observer: Observer) -> None:
        """
        Attach an observer to the subject.
        """
        pass

    @abstractmethod
    def detach(self, observer: Observer) -> None:
        """
        Detach an observer from the subject.
        """
        pass

    @abstractmethod
    def notify(self) -> None:
        """
        Notify all observers about an event.
        """
        pass

class ConcreteSubject(Subject):
    """
    The Subject owns some important state and notifies observers when the state
    changes.
    """

    _state: int = None
    """
    For the sake of simplicity, the Subject's state, essential to all
    subscribers, is stored in this variable.
    """

    _observers: List[Observer] = []
    """
    List of subscribers. In real life, the list of subscribers can be stored
    more comprehensively (categorized by event type, etc.).
    """

    def attach(self, observer: Observer) -> None:
        print("Subject: Attached an observer.")
        self._observers.append(observer)

    def detach(self, observer: Observer) -> None:
        self._observers.remove(observer)

    """
    The subscription management methods.
    """

    def notify(self) -> None:
        """
        Trigger an update in each subscriber.
        """

        print("Subject: Notifying observers...")
        for observer in self._observers:
            observer.update(self)

    def some_business_logic(self) -> None:
        """
        Usually, the subscription logic is only a fraction of what a Subject can
        really do. Subjects commonly hold some important business logic, that
        triggers a notification method whenever something important is about to
        happen (or after it).
        """

        print("\nSubject: I'm doing something important.")
        self._state = randrange(0, 10)

        print(f"Subject: My state has just changed to: {self._state}")
        self.notify()

class Observer(ABC):
    """
    The Observer interface declares the update method, used by subjects.
    """

    @abstractmethod
    def update(self, subject: Subject) -> None:
        """
        Receive update from subject.
        """
        pass

"""
Concrete Observers react to the updates issued by the Subject they had been
attached to.
"""

class ConcreteObserverA(Observer):
    def update(self, subject: Subject) -> None:
        if subject._state < 3:
            print("ConcreteObserverA: Reacted to the event")

class ConcreteObserverB(Observer):
    def update(self, subject: Subject) -> None:
        if subject._state == 0 or subject._state >= 2:
            print("ConcreteObserverB: Reacted to the event")

if __name__ == "__main__":
    # The client code.

    subject = ConcreteSubject()

    observer_a = ConcreteObserverA()
    subject.attach(observer_a)

    observer_b = ConcreteObserverB()
    subject.attach(observer_b)

    subject.some_business_logic()
    subject.some_business_logic()

    subject.detach(observer_a)

    subject.some_business_logic()

OUTPUT Subject: Attached an observer. Subject: Attached an observer.

Subject: I'm doing something important.
Subject: My state has just changed to: 0
Subject: Notifying observers...
ConcreteObserverA: Reacted to the event
ConcreteObserverB: Reacted to the event

Subject: I'm doing something important.
Subject: My state has just changed to: 5
Subject: Notifying observers...
ConcreteObserverB: Reacted to the event

Subject: I'm doing something important.
Subject: My state has just changed to: 0
Subject: Notifying observers...
ConcreteObserverB: Reacted to the event

评论 (0)

还没有评论,来抢沙发吧~

无需注册,留下昵称即可评论。

支持 Markdown 基本语法(链接会自动加 nofollow);不支持图片、HTML、代码高亮。