Java 9中观察者模式已被弃用,我们应该使用什么替代它?

172

Java 9发布了,Observer已经被弃用。

为什么会这样呢?这是否意味着我们不再需要实现观察者模式了呢?

知道有什么更好的替代方案会很有帮助。

6个回答

134

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

首先回答后面的问题 -

是的,这意味着你不应该再实现ObserverObervable了。

它们为什么已被弃用 -

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

Alex的回答很好地概述了Observer的一个缺点:所有的Observable都是相同的。你必须在Observable.update()方法中基于instanceof实现逻辑,并将对象转换为具体类型。

此外,还有一些错误,比如无法序列化Observable,因为它没有实现Serializable接口,而且它的所有成员都是私有的。

那有没有更好的替代方案呢?

另一方面,Listeners有许多类型,它们具有回调方法并且不需要转换。 正如@Ravi在他的答案中指出的那样,您可以使用PropertyChangeListener。对于其余部分,@Deprecation已标记为适当的文档,以探索其他包,如其他答案中所链接的那样。
请注意,废弃还标有分析,如此邮件所述-
这些天,任何遇到这些问题的人都可能是在误用RxJava或其他反应式流框架。在这种情况下,用户通常希望改用jdk9 java.util.concurrent.Flow API,所有反应式流框架都应与其计划中的jdk9兼容/互操作版本兼容。 编辑:还值得一提的是,API的弃用不仅仅是因为上述原因,还因为无法维护上述遗留代码,正如一些错误报告(上面链接)中的评论所述,这些错误报告提出了在某种程度上改善其实现的方法。

3
不错的回答,尽管我还在努力理解它。Java中的Observer是否已被弃用是因为设计模式本身存在某些固有问题(如GOF书中所定义的),还是由于Java对该模式的支持存在问题?在其他面向对象语言中,如C#、C ++、Python,观察者设计模式是否也像Java一样存在同样的问题? - Tim
37
某个具体实现已被弃用并不意味着观察者模式本身存在致命缺陷,“监听器”也是一种观察者。 - chrylis -cautiouslyoptimistic-
@chrylis 谢谢,完全同意。废弃API的主要原因之一是与其相关的维护工作,而且更改其实现可能会破坏其他代码。 - Naman
@curious95 在这里无法理解并发通知的方式 - Naman
当我调用notifyObservers()函数时,我添加的所有观察者都开始更新。这是否是并发(多线程)发生的? - curious95
4
@curious95 是的,调用notifyObservers()是并发的。这里有一个 codelet 来详细说明它的功能。 - Naman

48

有更多的原因:

不可序列化 - 由于Observable没有实现Serializable接口,因此您不能对其进行序列化,也不能对其子类进行序列化。

没有线程安全性 - 其方法可以被其子类覆盖,并且事件通知可能以不同的顺序和可能在不同的线程上发生,这足以破坏任何 "线程安全性"。

提供较少 -

它们不为应用程序提供丰富的事件模型。 例如,它们仅支持某些内容已更改的概念,但它们不提供有关已更改内容的任何信息

未解决问题 - 如上所述,曾经提出了许多重大问题(线程安全性、可序列化性),其中大部分都存在修复复杂性,并且仍然是未修复无活动开发,这就是为什么它已经被弃用的原因。

我还建议阅读这个答案为什么应该弃用观察者模式? ,@Jeff解释了弃用的其他原因。


那么我们有什么替代品呢?

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


PropertyChangeListener替换了Observer,但是我应该扩展/实现什么来代替Observable - LastStar007
2
更新:我认为方法是将PropertyChangeSupport作为实例变量添加,但我很感激确认。 - LastStar007
6
我认为你是正确的。我在Baeldung.com上找到了一段代码示例,正好符合这个要求。 - Dragos Stanciu
这很好地总结了为什么不要使用Observer和Observable。 - Sandeep Khantwal
Ravi,你能否请添加一个PropertyChange替代方案的示例?Dragos Stanciu提供了一个很有价值的示例。 - Dorad

23

为什么Observer在Java 9中已被废弃?

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

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

Observer模式的替代方法?

Observer设计模式有许多替代方案,其中之一是Reactive Streams。

Reactive Streams或Flow API:

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

Flow.Processor:既充当了Subscriber又充当了Publisher的组件。

Flow.Publisher:由Subscriber接收的项目的生产者。

Flow.Subscriber:消息的接收者。

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

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


11

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

由于Observer和Observable支持的事件模型相当有限,Observable提供的通知顺序未指定,并且状态更改与通知不是一一对应的。 要使用更丰富的事件模型,请考虑使用java.beans包。为了在线程之间实现可靠和有序的消息传递,请考虑使用java.util.concurrent包中的并发数据结构。要进行反应式流编程,请参见Flow API。


-1

目前您所写的回答不够清晰。请 [编辑] 添加更多细节,以帮助其他人理解它是如何回答问题的。有关如何编写优秀答案的更多信息,请参见帮助中心 - Community

-4
问题出在Java类/接口Observer、Observable等有缺陷的实现上,而不是GoF观察者模式本身。

4
为什么要回答?这个问题已经详尽地回答了,考虑了很多不同的观点。 - Snorik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接