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
包中的 PropertyChangeEvent
和 PropertyChangeListener
。
【讨论】:
PropertyChangeListener
替换 Observer
,但我应该扩展/实现什么来代替 Observable
?
更新:我认为方法是添加一个PropertyChangeSupport
作为实例变量,但我希望得到确认。
@LastStar007 我认为你是对的。我在Baeldung.com 上找到了一个代码示例。
这很好地总结了为什么不使用 Observer 和 Observable。【参考方案2】:
问题在于名为 Observer、Observable 等的 Java 类/接口的错误 Java 实现 - 但与 GoF 观察者模式无关。
【讨论】:
为什么是答案?这个问题已经得到了详细的回答,并考虑了很多不同的观点?【参考方案3】:这是为什么呢?这是否意味着我们不应该再实现观察者模式了?
先回答后半部分——
是的,这确实意味着您不应该再实施Observer
和Obervable
s。
Why were they deprecated -
他们没有为应用程序提供足够丰富的事件模型。例如,他们可以只支持某事发生了变化的概念,但没有传达任何关于发生了什么变化的信息。
Alex's answer 很好地说明了Observer
有一个弱点:所有Observable
s 都是一样的。您必须实现基于instanceof
的逻辑并将对象转换为具体类型到Observable.update()
方法中。
此外,还有一个类似 could not serialize the Observable
类的错误,因为它没有实现 Serializable
接口,并且它的所有成员都是私有的。
有什么更好的替代方案?
另一方面,Listeners
有很多类型,它们有回调方法,不需要强制转换。正如@Ravi 在他的answer 中指出的那样,您可以改用PropertyChangeListener
。
对于其余部分,@Deprecation
已标有适当的文档,以探索其他答案中链接的其他包。
请注意,弃用也标有 this mail 中所述的分析 -
这些天来,遇到这些的人可能会被他们击中 使用
RxJava
或其他反应流框架时出错。在 在这种情况下,用户通常会希望使用 jdk9java.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 中已被弃用,因为 Observer
和 Observable
支持的事件模型非常有限,通知的顺序由Observable
传递是未指定的,状态变化与通知不是一一对应的。
参见 Java 文档https://docs.oracle.com/javase/9/docs/api/java/util/Observable.html
观察者模式的替代方案?
观察者设计模式有很多替代方案,反应式流就是其中之一。
反应式流或流 API:
Flow
是Java 9中引入的一个类,有4个相互关联的接口:Processor
、Publisher
、Subscriber
和Subscription
。
Flow.Processor
:一个同时充当订阅者和发布者的组件。
Flow.Publisher
:订阅者收到的项目的生产者。
Flow.Subscriber
:消息的接收者。
Flow.Subscription
:链接Flow.Publisher
和Flow.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。我们应该使用啥来代替它?的主要内容,如果未能解决你的问题,请参考以下文章
在 API 29 java android 中不推荐使用 getBitmap