0
点赞
收藏
分享

微信扫一扫

设计模式——观察者模式

诗与泡面 2022-02-07 阅读 120

观察者模式

也被称为: 事件-订阅者模式,监听器模式

目的

观察者模式是允许你定义一个订阅机制去通知多个对象它们所观察的对象已经发生了某种事件的行为设计模式。
在这里插入图片描述

问题

想象一下有两个对象:顾客商店。顾客对某个品牌的商品(比如新出的iPhone)非常感兴趣,商店很快就会有进货。这个顾客可以每天都来店里看一遍查看商品是否到货。但如果商品仍在路上,这些旅程就显得毫无意义。
在这里插入图片描述
另一种方案就是当商品到货时,商店向所有用户发送电子邮件(对于部分用户而言这可能是垃圾邮件),这可以节省用户们多次去店里查看的时间。但与此同时,那些对该商品不感兴趣的用户会觉得十分失望。

这似乎有一个冲突,要么用户要耽误赴店查货的时间,要么商店就需要浪费资源向非目标用户发送消息。

方案

那个受人关注的对象我们一般称之为主体,但由于它也会向那些关注它的对象告知自己的状态变化,我们也称之为发布者。所有关注它的对象我们称之为订阅者。

观察者模式即是在发布者的类型定义中加入订阅机制,这样订阅者就可以订阅或取消订阅发布者的各种事件流。别害怕,所有这些完成起来都并不复杂。实际上这一机制需要以下操作:1)一个数组用于保存订阅者的引用;2)一对公共接口用于添加订阅者或移除订阅者。
在这里插入图片描述
这样当发布者有任何事件发生,将传递到它的订阅者那里并调用该对象特定的通知函数。实际的应用中同一个发布者类可能有多个不同的订阅者类都在追踪它的事件。你不希望将发布者绑定到所有这些类中。此外如果你的发布者类要被其他人使用,你甚至可能事先并不知情。

这就是为什么所有订阅者实现相同的接口以及发布者仅通过该接口与它们通信。这个接口应该声明通知方法以及一组参数,发布者可以使用这些参数在传递通知时附带一些上下文数据。
在这里插入图片描述

如果你的应用有几种不同类型的发布者,你想让你的订阅者与所有这些兼容,你可以更进一步让所有发布者遵循相同的接口。这个接口只需要描述几个订阅方法。该接口将允许订阅者在不耦合其具体类的情况下观察发布者的状态。

结构

在这里插入图片描述

  1. 发布者向其他对象发布感兴趣的事件。这些事件发生在发布者更改其状态或执行某些行为时。发布者类包含一个订阅列表,允许添加新订阅者或者删除已有的订阅者。
  2. 当发生新事件时,发布者遍历订阅列表并调用在每个订阅者对象上的订阅接口中声明的通知方法。
  3. 订阅者接口声明通知接口。在大多数情况下,它由一个update方法组成。该方法可能有几个参数,让发布者在更新时传递一些事件细节。
  4. 具体订阅者执行一些操作以响应发布者发出的通知。所有这些类都必须实现相同的接口,这样发布者就不会与某个具体的类耦合。
  5. 通常订阅者需要一些上下文信息来正确地处理更新。出于这个原因,发布者通常会传递一些上下文数据作为通知方法的参数。发布者可以将自己作为参数传递,让订阅者直接获取所需的任何数据。
  6. 客户端分别创建发行者和订阅者对象,然后为发布者注册订阅者用于之后的通知。

适用场景

当更改一个对象的状态可能需要更改其他对象,而这些联动的对象集是事先未知或动态变化的,可以使用观察者模式。
在处理图形用户界面的类时,经常会遇到这个问题。例如你创建了自定义按钮类并且希望让客户端将一些自定义代码关联到按钮上,以便在用户按下按钮时触发相关逻辑。

观察者模式允许任何实现订阅者接口的对象在发布者对象中订阅事件通知。您可以将订阅机制添加到按钮中,让客户端通过自定义订阅者类关联它们的自定义代码。

当你的应用程序中的一些对象必须观察其他对象,但只在有限的时间或特定的情况下,使用该模式。
订阅列表是动态的,因此订阅者可以在需要时加入或离开列表。

与其它设计模式的关联

  • 责任链模式,命令模式,中介者模式以及观察者模式都是用来处理多种情形下发送者和接收者的关联问题
    • 责任链模式
    • 命令模式
    • 调停者模式
    • 观察者模式
  • 中介者和观察者之间的区别通常是难以捉摸的。在大多数情况下你可以实现这些模式中的任何一个;但有时你可以同时申请。我们来看看怎么做。
  • 中介者的主要目标是消除一组系统组件之间的相互依赖关系。相反这些组件依赖于单个中介对象。观察者的目标是在对象之间建立动态的单向连接,其中一些对象作为其他对象的下属。

    中介者模式有一个流行的实现,它依赖于观察者。中介对象扮演发布者的角色,组件充当订阅或取消订阅中介事件的订阅者。当以这种方式实现中介者时,它看起来可能非常类似于观察者。

    当您感到困惑时,请记住您可以用其他方式实现中介者模式。例如可以将所有组件永久链接到同一个中介对象。这个实现不会类似于观察者,但仍然是中介者模式的一个实例。

    现在想象一个程序,其中所有组件都变成了发布者,允许彼此之间的动态关联。不会有集中的中介对象,只有一组分布式的观察者。

举报

相关推荐

0 条评论