观察者模式与事件驱动方法之间的区别


70

我总是发现观察者模式几乎与通常的事件驱动方法相似。实际上,我几乎相信它们实际上是指同一事物的不同名称。它们都使用相似的概念作为侦听器,甚至在实现中,它们几乎是同一件事,那就是具有回调方法/函数来执行操作。至少在Java中是这样。

用其他语言(如Actionscript / Flex)表示,事件对用户更友好,并且看起来似乎不仅仅是观察者模式定义的事情。但是,这些概念听起来是一样的。

但这是真的吗?观察者模式与通常的事件驱动编程风格一样吗?



Answers:


42

观察者模式是一个非常特殊的实例。事件驱动可能意味着任何事情。在大多数观察者模式实现中,观察者是监视观察者的对象。当观察者改变时,调用观察者的方法。严格来说,这不是“事件”。这意味着:对被观察者的各种不同动作通常会导致调用不同方法在观察者中。该方法改变了语义“什么”。在事件驱动系统中,您基本上有一个使用对象/方法,并且该消息说明事件中发生了更改或发生了什么。那可以是任何东西,而不仅限于观察某些东西!这意味着:在事件驱动系统中,您可以通过添加新的事件类型来获得新的语义。在观察者模式中,通常通过向Observer类添加方法来添加语义。但是,没有人阻止您将Observer实施为ChangeEvent的特殊侦听器。


171
读这本书使我更加困惑。
暗恋

@crush我可以添加一个示例进行更多说明,在Java中,EDT是事件总线,它捕获系统发送的所有事件,比如说按钮单击,EDT将调度click事件,按钮将捕获它-note按钮的父容器也可以捕获事件,而按钮本身也可以捕获其他类型的事件,这是事件模式的一个示例。现在该按钮已注册了侦听器,并从发出此事件的按钮中得到了通知并调用了该侦听器,此注册是观察者模式的一个示例
DrAhmedJava

4
那么,事件就像没有预期接收者的广播,而观察者模式就像组播,接收者直接观察来自可观察者的信号吗?
Gulshan

1
在大多数观察者模式实现中,逻辑上的含义之一是观察者是观察对象的对象,为了正确地称为对象模式,对象观察者和被观察者必须具有单一的分离度(例如,观察者直接观察对象观察者),如果是这样的话,这将与事件驱动型有所不同吗?
彼得·大卫·卡特

31

当发布者或主题的状态发生变化时,

  • 事件驱动的体系结构(是一种消息驱动的体系结构),负责异步地消息传递到订阅服务器。

  • 观察者模式(一种软件设计模式),负责命令订阅服务器同步执行某项操作。


20

事件驱动编程是定义范例的术语。而“ 可观察模式”是使事件驱动应用程序的设计解决方案。

干杯!


11

差异之一可能是,事件系统始终具有一个eventdispatchthread,该线程将可观察对象与其观察者解耦,因此事件可能不会立即到达观察者。真正的可观察对象直接调用观察者方法,而事件驱动的可观察对象将其事件放入事件队列中。然后,EDT将这些事件传递给已注册的侦听器。


10

从这个问题的多个答案,这篇hackernoon文章以及我自己的经验综合而成,在我看来,观察者模式与事件驱动(例如,Pub-Sub)架构之间的主要区别在于:

在Observer模式中,OBSERV保持其OBSERV引用ERS

在Pub-Sub中,广播者不知道其监听者是谁。(或者,即使有人在监听。)监听器可能希望广播者提供一些数据,但不知道事件的确切来源。也许它来自多个类或远程系统。也许不吧。广播者或侦听器都没有关系。

现在,并不是说这些事情有很大的不同。此外,有些实现的行为与这两者之一或两者相同。

例如,根据您的需要,微风宝石可以让您像观察者模式或Pub-Sub模式一样工作。如果愿意,您甚至可以将两者一起使用。


2

我已经搜索了同样的问题。对于该线程,我从Angel O'Sphere的“什么语义”中找到要点,从Spacerat的“ Dispatcher”的观点中找到了帮助。

我认为这两点使Even-Driver和Observer Pattern区别开来。至少从规范的解释来看,“观察者模式”通常表示一旦“主题”已更改并且通过调用订户或侦听器提供的接口来实现“调度”的即时广播。对于事件驱动,在“主题”和“观察者”之间总是存在另一层。称为“分派器”或使用“事件队列”。这提供了“延迟”处理以减少CPU使用率,并且还提供了某些调用不同对象的能力。接口取决于不同的事件类型。


2

我尝试非常简单,因为它也对我有帮助。

只需将其视为观察者和可观察者即可。相反,可观察对象将setChanged标记为setChanged,而观察者向观察对象请求已更改的内容,则可观察对象将具有有关更改的所有相关信息的对象(事件携带状态)广播给观察者。因此,观察者与可观察者之间实际上还有一个实例。

http://www.grahambrooks.com/event-driven-architecture/patterns/stateful-event-pattern/


2

关于观察者模式的一大优点是安全性。当被观察者对象内发生代码更改时,所有观察者都必须实现新的更改。如果我们改用事件,则事件侦听器将不会对新事件的实现做出反应。换句话说,观察者指示事件必须由观察者处理。

在我的一个项目中,我遇到了一种情况,其中一个被观察者的物体被破坏了,在这样做之前需要通知观察者。我唯一要做的就是将通知添加为所有观察员的要求,并在观察员被摧毁之前触发事件。这样做的好处是,只有在所有观察者都为新创建的事件实现了处理程序的情况下,代码才会编译,因此您不太可能忘记更改其中的一些事件。就我而言,我有大量的可能的观察者,很高兴知道我可以进行更改而不会产生一些或多个隐藏的错误。

这些特质使观察者模式的灵活性不如简单地引发事件,而是让观察者自己决定。但是,在使用事件时,要提防那些隐藏在拐角处的伟大的意大利面怪物,并且只有在截止日期临近时才会出现。像我一样,你们中可能有不止一个人遇到过这个丑陋的野兽。

换句话说,要尽可能务实,仍然使用正确的工具来完成工作。这意味着在需要灵活性时使用事件,在需要控制时使用观察者。


1

是的,它们基本上是相同的。

事件类似于某些语言的“内置”观察者模式模板。

因此,您实际上不会以支持事件的语言来实现观察者模式,因为事件已经提供了您想要的内容。
另一方面,您可以使用观察者模式以缺少事件的语言编写事件驱动的代码。


我想说的是Observer / Pubsub模式与简单事件之间的最大区别是事件的大量使用会在系统中的对象之间引入非常紧密的耦合,而作为中介的观察者或集线器则会促进松散耦合-订阅的对象特定主题的链接不需要发布主题的对象的任何“知识”。
natlee75 '02

1

两者的基本区别是耦合和同步行为。如果我们坚持观察者模式,我们说只有一个信号源,它将是同步的;而另一方面,如果发生事件,我们将双方分离开来独立工作,而同时也有可能拥有多个信号源。将来发生的事件,无需任何代码更改。事件帮助我们将异步视为设计。所有的Reactive编程库都为事件驱动的设计提供了很好的支持。


0

维基百科

观察者模式是一种软件设计模式,在该模式中,称为主题的对象会维护其依赖项的列表(称为观察者),并通常通过调用其方法之一来自动通知状态更改。

它主要用于在“事件驱动”软件中实施分布式事件处理系统。大多数现代语言(例如Java和C#)都内置了“事件”结构,这些结构实现了观察者模式组件,以便于编程和编写短代码。

观察者模式更加抽象和理论化。事件是一种(通常是内置的)实现,但是如Angel的回答所述,除了观察者模式中严格定义的内容以外,事件还可以在其他几种情况下使用。


0

事件驱动是对象使用事件进行通信的软件范例或编写代码的样式。某些语言(例如C#)对事件具有本机支持。您可以让一个对象引发另一个对象侦听的事件。观察者模式是获得相同结果的另一种方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.