【问题标题】:Difference between Observer Pattern and Event-Driven Approach观察者模式和事件驱动方法的区别
【发布时间】:2011-09-20 08:05:19
【问题描述】:

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

在其他语言中,比如 Actionscript/Flex,事件对用户更加友好,并且看起来它所做的不仅仅是观察者模式定义的。但是,这些概念听起来还是一样的。

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

【问题讨论】:

标签: events design-patterns observer-pattern


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      综合这个问题的多个答案,这个hackernoon article,以及我自己的经验,在我看来,观察者模式和事件驱动(例如发布订阅)架构之间的主要区别是:

      在观察者模式中,被观察者ed维护对其观察者ers的引用。

      而在 Pub-Sub 中,广播者不知道其听众是谁。 (或者即使有人在那里收听。)Listener 可能期望来自 Broadcaster 的一些数据,但不知道事件的确切来源。也许它来自多个类或远程系统。也许不吧。对广播者或听众来说都没有关系。

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

      例如,wisper rubygem 允许您根据需要像观察者模式或 Pub-Sub 模式一样行事。如果您愿意,您甚至可以同时使用两者。

      【讨论】:

        【解决方案4】:

        我尝试很简单,因为这也帮助了我一次。

        只需将其视为观察者和可观察者。相反,observable 标记了 setChanged 并且观察者从 observable 请求发生了什么变化,observable 向观察者广播了一个对象(事件承载状态),其中包含有关更改的所有相关信息。所以实际上 Observer 和 Observable 之间多了一个实例。

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

        【讨论】:

          【解决方案5】:

          事件驱动编程是一个定义范式的术语。然而 可观察模式是一种设计解决方案,用于制作应用程序 事件驱动。

          干杯!

          【讨论】:

            【解决方案6】:

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

            • 事件驱动架构(一种消息驱动的架构),负责异步传递消息给订阅者。

            • 观察者模式(是一种软件设计模式),负责命令订阅者同步做某事。

            【讨论】:

              【解决方案7】:

              来自Wikipedia

              观察者模式是一种软件设计模式,其中一个对象, 称为主体,维护其依赖项的列表,称为 观察者,并自动通知他们任何状态变化, 通常通过调用他们的方法之一。

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

              观察者模式更加抽象和理论化。事件是一个(通常是内置的)实现,但正如 Angel 的回答中指出的那样,除了观察者模式中严格定义的情况之外,事件往往能够在其他一些情况下使用。 p>

              【讨论】:

                【解决方案8】:

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

                【讨论】:

                  【解决方案9】:

                  我已经搜索了一些相同的问题。 对于这个线程,我发现 Angel O'Sphere 关于“What semantics”的观点和 Spacerat 关于“Dispatcher”的观点确实有帮助。

                  这两点是我的理解,将 Even-Driver 与 Observer Pattern 区分开来。至少从规范的解释来看,“观察者模式”通常表示一旦“主题”发生变化时立即广播,“调度”是通过调用订阅者或侦听器提供的接口来实现的。而对于事件驱动,在“Subject”和“Observer”之间总是有另一层。要么称为“Dispatcher”,要么使用“Event Queue”。这提供了“延迟”处理以减少CPU使用率,也提供了一定的调用不同的能力接口取决于不同的事件类型。

                  【讨论】:

                    【解决方案10】:

                    第一个区别可能是,Event-Systems 总是有一个 eventdispatchthread,它将 observables 与其观察者分离,因此事件可能不会立即到达观察者。虽然真正的 observable 直接调用观察者方法,但事件驱动的 observable 将它们的事件放入事件队列中。然后 EDT 将这些事件传递给注册的侦听器。

                    【讨论】:

                      【解决方案11】:

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

                      【讨论】:

                      • 读到这里让我更加困惑。
                      • @crush 我可以添加一个示例以更清楚地说明,在 Java 中,EDT 是一个事件总线,它捕获系统发送的所有事件,比如说按钮单击,EDT 将调度单击事件,按钮将捕获它——注意按钮的父容器也可能捕获事件,而按钮本身可能捕获其他类型的事件——这是事件模式的一个示例。现在按钮已经注册了监听器,从传递这个事件的按钮得到通知和调用,这个注册是观察者模式的一个例子
                      • 那么,事件就像没有预期接收者的广播,而观察者模式就像多播,接收者直接观察来自 observable 的信号?
                      • 在大多数观察者模式实现中的逻辑含义之一,观察者是一个观察被观察者的对象,为了被正确地称为对象模式,对象观察者和观察者必须有单一程度的分离(例如观察者直接观察被观察者),如果是这样,这是否会构成与事件驱动的差异,或者不是这种情况?
                      【解决方案12】:

                      是的,它们基本相同。

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

                      因此,您不会在支持事件的语言中真正实现观察者模式,因为它们已经提供了您正在寻找的内容。
                      另一方面,您可以使用观察者模式在缺少事件的语言中编写事件驱动。

                      【讨论】:

                      • 我想说观察者/发布订阅模式和直接事件之间的一个很大区别是,大量使用事件会在系统中的对象之间引入非常紧密的耦合,而观察者或集线器作为中介促进更松散的耦合 - 订阅特定主题的对象不需要对发布该主题的对象有任何“知识”。
                      猜你喜欢
                      • 1970-01-01
                      • 2010-10-22
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-11-23
                      • 1970-01-01
                      • 1970-01-01
                      • 2021-07-09
                      • 2021-04-04
                      相关资源
                      最近更新 更多