Java 9 中不推荐使用 Observer。我们应该使用啥来代替它?

Posted

技术标签:

【中文标题】Java 9 中不推荐使用 Observer。我们应该使用啥来代替它?【英文标题】:Observer is deprecated in Java 9. What should we use instead of it?Java 9 中不推荐使用 Observer。我们应该使用什么来代替它? 【发布时间】:2018-03-04 22:33:00 【问题描述】:

Java 9 出来了,Observer 已被弃用。 这是为什么?这是否意味着我们不应该再实现观察者模式了?

最好知道什么是更好的选择?

【问题讨论】:

【参考方案1】:

还有更多原因:

Not Serializable - 因为,Observable 没有实现 Serializable。所以,你不能序列化 Observable 和它的子类。

No Thread Safety - 方法可以被其子类覆盖,事件通知可以以不同的顺序发生,并且可能发生在不同的线程上,这足以破坏任何“线程安全”。 p>

Less to offer -

它们没有为应用程序提供足够丰富的事件模型。为了 例如,他们只支持某些事情已经改变的概念,但是 他们没有传达任何关于发生了什么变化的信息

未解决的问题 - 如前所述,提出了许多重大问题(线程安全、可序列化),其中大多数问题需要修复且仍然“未修复”或 没有积极开发,这就是它被弃用的原因。

我还建议阅读此答案Why should the observer pattern be deprecated?,@Jeff 已经解释了弃用的其他原因。


那么,我们有什么替代方案?

您可以使用 java.beans 包中的 PropertyChangeEventPropertyChangeListener

【讨论】:

PropertyChangeListener 替换 Observer,但我应该扩展/实现什么来代替 Observable 更新:我认为方法是添加一个PropertyChangeSupport 作为实例变量,但我希望得到确认。 @LastStar007 我认为你是对的。我在Baeldung.com 上找到了一个代码示例。 这很好地总结了为什么不使用 Observer 和 Observable。【参考方案2】:

问题在于名为 Observer、Observable 等的 Java 类/接口的错误 Java 实现 - 但与 GoF 观察者模式无关。

【讨论】:

为什么是答案?这个问题已经得到了详细的回答,并考虑了很多不同的观点?【参考方案3】:

这是为什么呢?这是否意味着我们不应该再实现观察者模式了?

先回答后半部分——

是的,这确实意味着您不应该再实施ObserverObervables。

Why were they deprecated -

他们没有为应用程序提供足够丰富的事件模型。例如,他们可以只支持某事发生了变化的概念,但没有传达任何关于发生了什么变化的信息。

Alex's answer 很好地说明了Observer 有一个弱点:所有Observables 都是一样的。您必须实现基于instanceof 的逻辑并将对象转换为具体类型到Observable.update() 方法中。

此外,还有一个类似 could not serialize the Observable 类的错误,因为它没有实现 Serializable 接口,并且它的所有成员都是私有的。

有什么更好的替代方案?

另一方面,Listeners 有很多类型,它们有回调方法,不需要强制转换。正如@Ravi 在他的answer 中指出的那样,您可以改用PropertyChangeListener

对于其余部分,@Deprecation 已标有适当的文档,以探索其他答案中链接的其他包。


请注意,弃用也标有 this mail 中所述的分析 -

这些天来,遇到这些的人可能会被他们击中 使用RxJava 或其他反应流框架时出错。在 在这种情况下,用户通常会希望使用 jdk9 java.util.concurrent.Flow 所有反应流框架的 API 应该在他们计划的即将到来的范围内兼容/互操作 jdk9 兼容版本。

编辑:还值得一提的是,API 的弃用不仅主要是因为上述原因,还因为无法维护上述遗留代码在一些错误报告(上面链接)的 cmets 中,提出这些报告是为了以一种或另一种方式标记其实施的改进。

【讨论】:

+1。很好的答案,尽管我仍在努力理解它。 Java 中的 Observer 是否由于设计模式本身的一些固有问题(如 GOF 书中所定义)或 Java 对模式的支持问题而被弃用?在其他 OO 语言中,例如 C#、C++、Python,观察者设计模式是否也存在与 Java 相同的问题? 不推荐使用特定实现的事实并不意味着观察者 pattern 存在致命缺陷。 Listener 也是一个观察者。 @chrylis 谢谢,完全同意,弃用 API 的主要原因之一也是对其附加的维护,更改其实现可能会破坏其他代码。 @curious95 无法理解通知并发的方式那里。 @curious95 是的,调用 notifyObservers() 是并发的。这是来自同一共享的codelet,以详细解释其功能。【参考方案4】:

为什么在 Java 9 中不推荐使用 Observer?

Ans: Observable 类和 Observer 接口在 Java 9 中已被弃用,因为 ObserverObservable 支持的事件模型非常有限,通知的顺序由Observable 传递是未指定的,状态变化与通知不是一一对应的。

参见 Java 文档https://docs.oracle.com/javase/9/docs/api/java/util/Observable.html

观察者模式的替代方案?

观察者设计模式有很多替代方案,反应式流就是其中之一。

反应式流或流 API

Flow是Java 9中引入的一个类,有4个相互关联的接口:ProcessorPublisherSubscriberSubscription

Flow.Processor :一个同时充当订阅者和发布者的组件。

Flow.Publisher:订阅者收到的项目的生产者。

Flow.Subscriber:消息的接收者。

Flow.Subscription:链接Flow.PublisherFlow.Subscriber 的消息控件。

参见 Java 文档https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/Flow.html

【讨论】:

【参考方案5】:

考虑到 Observable 类和 Observer 接口自 Java 9 起已被弃用。根据帖子 Java's Observer and Observable Are Deprecated in JDK 9

Observer 和 Observable 支持的事件模型相当有限, Observable 传递的通知的顺序是未指定的,并且 状态变化不是一一对应的 通知。 对于更丰富的事件模型,请考虑使用 java.beans 包裹。对于线程之间可靠且有序的消息传递,请考虑 使用其中一种并发数据结构 java.util.concurrent 包。如需反应式流式编程,请参阅 Flow API。

【讨论】:

以上是关于Java 9 中不推荐使用 Observer。我们应该使用啥来代替它?的主要内容,如果未能解决你的问题,请参考以下文章

什么是线程组,为什么在Java中不推荐使用?

什么是线程组,为什么在Java中不推荐使用?

什么是线程组,为什么在 Java 中不推荐使用?

在 API 29 java android 中不推荐使用 getBitmap

为啥 Java 中不推荐将 Optional 当做参数使用?

为啥 Java 中不推荐将 Optional 当做参数使用?