跳到主要内容

观察者模式

观察者模式定义了一种一对多的订阅关系,当一个对象的状态发生变化时,所有订阅它的对象都会得到通知。

结构

观察者模式示意图观察者模式示意图

观察者模式中,发布者(Publisher)对象维护了一个订阅者列表,并提供了订阅、退订和通知订阅者的方法。发布者对象在特定事件发生时会通知所有订阅者对象。具体订阅者对象通过实现订阅者(Subscriber)接口来接收通知。

备注

事实上,也可以将业务代码与发布者解耦,使得发布者仅负责通知订阅者,而不关心具体的业务逻辑。这样可以使得发布者对象更加通用,更易于复用。

信息

不难注意到观察者模式和 中介者模式 的相似之处。两者都是用于解耦组件之间的通信,但存在以下不同:

  • 中介者的主要目标是消除一系列系统组件之间的相互依赖。观察者的目标是在对象之间建立动态的单向连接, 使得部分对象可作为其他对象的附属发挥作用。
  • 中介者模式可以基于观察者模式实现,但是也可采用其他方式来实现。
  • 中介者常常是中心化的,而观察者模式中的发布者可以是分布式、去中心化的。

应用场景

  • 当一个对象状态的改变需要动态改变其他对象时

优缺点

优点

  • 开闭原则:你无需修改发布者代码就能引入新的订阅者类。
  • 在运行时建立对象之间的动态联系。

缺点

  • 观察者模式不保证通知的顺序。

代码示例

下面通过一个简单的新闻订阅系统展示了观察者模式的实现。

NewsAgency发布者(也叫主题或可观察者),它维护一个订阅者列表,并有一个 _state 属性来存储最新的新闻。当 publish_news 方法被调用时,它的状态会改变,然后它会调用 notify 方法来通知所有已注册的观察者

Observer 是一个接口,定义了所有具体观察者必须实现的 update 方法。NewsReader 是一个具体的观察者,它实现了 update 方法,以便在收到发布者的通知时做出反应(在这里是打印新闻)。

客户端代码创建了发布者和多个观察者,并将观察者附加到发布者上。当发布者发布新消息时,所有附加的观察者都会自动收到通知并更新自己的状态,而发布者和观察者之间没有紧密的耦合关系。