观察者设计模式

观察者模式(Observer Design Pattern),也被称为发布订阅模式(Publish-Subscribe Design Pattern),它适用于当对象间存在一对多的依赖关系;当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并更新自身。

在观察者模式中,被依赖的对象被称为被观察者,所以依赖于它的对象被称为观察者,一般来说,同一种观察中,只能有一个被观察者,以及若干个观察者。

实际上,观察者模式是一个比较抽象的模式,根据不同的应用场景和需求,有完全不同的实现方式,也有非常多叫法,比如:Subject-Observer、Publisher-Subscriber、Producer-Consumer、EventEmitter-EventListener、Dispatcher-Listener。不管怎么称呼,只要应用场景符合刚刚给出的定义,都可以看作观察者模式。

优缺点

优点

  1. 观察者和被观察者是抽象耦合的。
  2. 基于抽象接口编程,定义观察者非常方便。
  3. 观察者功能单一,符合单一职责原则。

缺点

  1. 解耦后,可读性变弱,需要理解模式本身才能更好理解代码。
  2. 如果观察者很多,将所有的观察者都通知到会花费很多时间,尤其在同步阻塞的情况下。

应用场景

观察者模式可以说是一个应用场景非常广泛的设计模式,比如,邮件订阅、RSS Feeds,计算机的广播通信,都是观察者模式。本质上来说,只要符合观察者模式定义的对象之间一对多的依赖关系,都可以是观察者模式。

观察者模式的构成

观察者模式的构成并不复杂,主要就是需要定义好解耦后,观察者与被观察者之间的交互方式,据此可以划为以下四类:

  • 观察者抽象类 :定义观察者需要实现的接口规范。
  • 被观察者抽象类 :定义被观察者需要实现的接口规范。
  • 具体的观察者类 :继承观察者抽象类,并实现逻辑。
  • 具体的被观察者类: 继承被观察者抽象类,并实现逻辑。

通过一个消息推送的例子来说明。
当我们希望某个消息推送给一批人,并且可以不断的添加或减少要推送的特定群体。
背后做的事情,就是维护一个推送列表,也即是观察者,当有新消息时,推送给列表中的所有群体。

观察者抽象类

class Observer:
    @abstractmethod
    def update(self):
        """观察者自己的方法"""
        pass

定义了观察者需要实现 update 方法,在被通知后需要执行。

被观察者抽象类

class Subject:
    def __init__(self):
        self.observer_list = []

    @abstractmethod
    def addObserver(self, observer: Observer):
        """添加一个观察者"""
        pass

    @abstractmethod
    def removeObserver(self, observer: Observer):
        """移除一个观察者"""
        pass

    @abstractmethod
    def notify(self):
        """通知所有观察者"""
        pass

定义了被观察者的规范,需要实现添加、删除观察者,以及通知所有观察者的方法。

具体的被观察者类

class ConcreteSubject(Subject):

    def addObserver(self, observer: Observer):
        self.observer_list.append(observer)

    def removeObserver(self, observer: Observer):
        self.observer_list.remove(observer)

    def notify(self):
        [i.update() for i in self.observer_list]

具体的观察者类

class ConcreteObserver1(Observer):
    def update(self):
        print("ConcreteObserver1 的 update 方法")


class ConcreteObserver2(Observer):
    def update(self):
        print("ConcreteObserver2 的 update 方法")

不同的具体观察者,实现的 update 方法不尽相同。

具体使用

# 创建一个主题,也就是被观察者
subject = ConcreteSubject()

# 添加两个观察者
observer1, observer2 = ConcreteObserver1(), ConcreteObserver2()
subject.addObserver(observer1)
subject.addObserver(observer2)

# 通知观察者
subject.notify()

# ===== 输出 =====
ConcreteObserver1 的 update 方法
ConcreteObserver2 的 update 方法

总结

观察者模式在现实中的应用场景是非常广泛的,并且有非常多成熟的应用。可以同步阻塞实现,也可以异步非阻塞实现,可以是进程内,也可以是跨进程方式,不同的实现方式,具体的实现也不一样,但是底层的设计思想是一致的。

所以这也告诉我们,掌握基本的基础知识和指导思想,怎么扩展,都是在这些基础上添砖加瓦,万变不离其宗,学好基础很重要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tlqwanttolearnit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值