首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >观察者模式和侦听器之间有什么区别?

观察者模式和侦听器之间有什么区别?
EN

Software Engineering用户
提问于 2018-09-20 20:50:08
回答 3查看 18.4K关注 0票数 7

我使用了某种类型的“监听器”,在这种情况下,需要通知某些事件的类实现了一个接口(例如: CurrencyListener,有一个方法currencyUpdated(货币)),然后,需要发送通知的对象有一个侦听器列表(列表),并且只在调用currencyUpdated(货币)方法的列表上迭代。

这个监听器的结构非常类似于观察者模式,没有观察者和可观察的类,只有监听器接口(CurrencyListener)。

使用一种方法比另一种方法有什么好处/缺点?

EN

回答 3

Software Engineering用户

发布于 2018-09-20 23:08:51

这是观察者的模式-这是完全一样的东西。

我使用了某种类型的“侦听器”,在这种情况下,需要通知某些事件的类实现了一个接口(例如: CurrencyListener,带有currencyUpdated(货币)方法)。

在观察者模式中,您有一个抽象(接口或基类)观察者,它定义了观察者可以观察(或侦听)的东西。您的CurrencyListener是观察者。

模式的另一部分是可观察的,它是发送通知的对象,它本身可能是抽象的,也可能不是某种层次结构的一部分。即,该模式不要求存在ConcreteObservable子类。在Go4模式书中,ConcreteObservable的一个角色被描述为

“存储ConcreteObserver对象感兴趣的状态。”

如果ConcreteObserver不需要任何特殊的状态,或者只可以使用可观察的基类提供的接口,那么就不需要ConcreteObservable。

然后,需要发送通知的对象有一个侦听器(列表)列表,并且只在调用currencyUpdated(货币)方法的列表上迭代。

观察者为可观察的/侦听器提供了向其注册的方法,并在内部维护这些侦听器的集合。你的目标就是这么做的。

再说一次,这只是经典的观察者模式。观察者和可观察对象是相互独立的,因为它们都依赖于观察者接口提供的抽象,也因为它们依赖于客户端代码来将观察者/侦听器与可观察的对象连接起来。

在这个模式上有许多不同的变化,不同语言中的许多特性都是伪装的观察者模式。例如,在C#中,事件显然是模式的变化。另一个变体的例子是通常被称为Messenger (或者像Martin Fowler所说的事件聚合器),它可以在一些库和框架中找到--它是一个类,充当观察者和观测者之间的中介。结构略有不同,但它基于观察者模式;实际上,Go4书在描述模式的实现部分的末尾描述了类似的东西(他们称之为ChangeManager)。

票数 7
EN

Software Engineering用户

发布于 2018-09-20 22:16:38

In

你的听众非常接近观察者。然而,它们似乎与一个非常具体的观察主题(如Currency)紧密相连。因此,侦听其他类型的主题将需要额外的侦听器接口和类似的调度方法的额外实现。

相反,原始的观察者模式通过在观察的主题(以下称为可观察的)和观察者之间提供抽象的耦合来确保可重用和可扩展。这允许模式的每一方进一步独立地进行专门化。

总之,你的听众并不是完全的观察者。

In long,包含了大量的细节

您的设计

我理解以下设计:

  • 您的具体侦听器都使用特定的方法CurrencyListener实现CurrencyListener.currencyUpdated(Currency currency)接口。
  • 您有其他监听器接口,用于与其他实现进行其他类型的更新。
  • 通知发件人持有CurrencyListener的列表,
  • 通知发件人遍历此列表并激发它们的currencyUpdated()方法。

未决问题:

  • 您不知道如何向通知发件人添加/删除侦听器。这不是一个主要的问题,但观察者的模式可能会在这一点上激励你。
  • 您不知道侦听器是否使用通知发件人的状态(对于观察者来说是典型的),也不知道货币是否是侦听器所侦听的对象(观察者模式的典型变体,当同一个观察者必须查看多个可观测值时使用)。从此以后,我将假定后者。

用观察者模式

映射您的设计

将您的设计与观测器设计模式进行比较表明:

  • 通知发件人是Observable (除非Currency是)
  • 侦听器列表是Observer的集合。
  • CurrencyListener是一个Observer接口
  • CurrencyUpdated()方法是update()方法。
  • 具体侦听器是具体的Observer

有什么区别?

  • 通知发送方和您的货币不是抽象接口,而是一个具体的类。它们似乎都不是提供足够抽象的接口的通用类。这意味着您的观察者都依赖于这个具体的类(强耦合而不是抽象耦合)。
  • 观察者模式具有将观察员添加/移除到可观察对象的注册机制。(但也许你也有,但没有说出来?)
  • 您的CurrencyListener强加了update函数将接收的对象的具体类型。这种类型似乎非常具体,并与通知发送方密切联系。因此,为一种新的可观测对象实现侦听器每次都需要一个新的接口。
  • 相反,Observer.update()不需要知道具体的Observable。这允许将实现解耦。混凝土Observer知道混凝土Observable,并能得到它的状态。一个已知的变体是Observer.update(Observable o)。因此,观察者仍然与可观察到的具体实现(也)脱钩。

Conclusions:

你的听众都很好。如果你只有一种可观察的科目,他们甚至可以简化设计。

但是,使用观测器模式对它们进行重构可能有助于将部件解耦,这将有助于重用和提高灵活性。

票数 4
EN

Software Engineering用户

发布于 2019-07-28 01:26:23

它们是一样的,观察者模式是一种模式,侦听器是基于该模式的实现。

其他答案只是指出了命名方法的方式并不能使您的观察者系统可重用。因此,只需尝试使用"update“而不是"updateCurrency”来命名该方法。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/378748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档