为什么会这样?这是不是意味着我们不应该再实现观察者模式了?
首先回答后面的问题 -
是的,这意味着你不应该再实现Observer
和Obervable
了。
它们未能为应用程序提供丰富的事件模型。例如,它们只支持某些事情已经发生了变化的概念,但没有传达任何关于发生了什么变化的信息。
Alex的回答很好地概述了Observer
的一个缺点:所有的Observable
都是相同的。你必须在Observable.update()
方法中基于instanceof
实现逻辑,并将对象转换为具体类型。
此外,还有一些错误,比如无法序列化Observable
类,因为它没有实现Serializable
接口,而且它的所有成员都是私有的。
那有没有更好的替代方案呢?
另一方面,Listeners
有许多类型,它们具有回调方法并且不需要转换。 正如@Ravi在他的答案中指出的那样,您可以使用PropertyChangeListener
。对于其余部分,@Deprecation
已标记为适当的文档,以探索其他包,如其他答案中所链接的那样。
RxJava
或其他反应式流框架。在这种情况下,用户通常希望改用jdk9 java.util.concurrent.Flow
API,所有反应式流框架都应与其计划中的jdk9兼容/互操作版本兼容。
编辑:还值得一提的是,API的弃用不仅仅是因为上述原因,还因为无法维护上述遗留代码,正如一些错误报告(上面链接)中的评论所述,这些错误报告提出了在某种程度上改善其实现的方法。有更多的原因:
不可序列化 - 由于Observable没有实现Serializable接口,因此您不能对其进行序列化,也不能对其子类进行序列化。
没有线程安全性 - 其方法可以被其子类覆盖,并且事件通知可能以不同的顺序和可能在不同的线程上发生,这足以破坏任何 "线程安全性"。
提供较少 -
它们不为应用程序提供丰富的事件模型。 例如,它们仅支持某些内容已更改的概念,但它们不提供有关已更改内容的任何信息
未解决问题 - 如上所述,曾经提出了许多重大问题(线程安全性、可序列化性),其中大部分都存在修复复杂性,并且仍然是未修复或无活动开发,这就是为什么它已经被弃用的原因。
我还建议阅读这个答案为什么应该弃用观察者模式? ,@Jeff解释了弃用的其他原因。
您可以使用java.beans
包中的PropertyChangeEvent
和PropertyChangeListener
。
PropertyChangeListener
替换了Observer
,但是我应该扩展/实现什么来代替Observable
? - LastStar007PropertyChangeSupport
作为实例变量添加,但我很感激确认。 - LastStar007为什么Observer在Java 9中已被废弃?
答:在Java 9中,Observable
类和Observer
接口已被废弃,因为Observer
和Observable
支持的事件模型非常有限,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个相关的接口:Processor
、Publisher
、Subscriber
和Subscription
。
Flow.Processor
:既充当了Subscriber又充当了Publisher的组件。
Flow.Publisher
:由Subscriber接收的项目的生产者。
Flow.Subscriber
:消息的接收者。
Flow.Subscription
:链接Flow.Publisher
和Flow.Subscriber
的消息控制。
请参阅Java文档https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/Flow.html
考虑到自Java 9起,Observable
类和Observer
接口已被弃用。根据此文Java's Observer and Observable Are Deprecated in JDK 9。
由于Observer和Observable支持的事件模型相当有限,Observable提供的通知顺序未指定,并且状态更改与通知不是一一对应的。 要使用更丰富的事件模型,请考虑使用
java.beans
包。为了在线程之间实现可靠和有序的消息传递,请考虑使用java.util.concurrent
包中的并发数据结构。要进行反应式流编程,请参见Flow API。
notifyObservers()
是并发的。这里有一个 codelet 来详细说明它的功能。 - Naman