Observer 和 Observable 被弃用了,原因是:它们传达了一些变化但没有说明发生了什么变化,这是错误的吗?
Observer and Observable got deprecated and the reason stated is: they convey something has changed but not state what has changed, this is false?
Check this by open jdk
deprecate Observer and Observable
Observer 和 Observable Class:
可观察到:-
class NewsAgency extends Observable {
String news;
public void setNews(String news) {
this.news = news;
setChanged();
notifyObservers(news);
}
}
观察者:-
public class IndiaNews implements Observer {
@Override
public void update(Observable o, Object news) {
System.out.println("Indianews: " +news.toString());
}
}
class AjjTak implements Observer {
@Override
public void update(Observable o, Object news) {
System.out.println("AjjTak: " +news.toString());
}
主要CLass:-
public class Main {
public static void main(String[] args) {
NewsAgency newsAgency = new NewsAgency();
IndiaNews indiaNews = new IndiaNews();
AjjTak ajjTak = new AjjTak();
newsAgency.addObserver(indiaNews);
newsAgency.addObserver(ajjTak);
newsAgency.setNews("Yo");
}
}
但是我能够告诉观察者消息已经改变
那么上面的说法怎么是真的呢?
谁能帮我理清思路?
谢谢:)
But I was able to tell the observer that news has changed then. How that above statement is true?
issue tracker link 中的文字说:
"For example, they support only the notion that something has changed, but they don't convey any information about what has changed."
在您的示例中,update
方法调用告诉观察者发生了一些变化,但实际上并没有发生变化。因此,当您调用 setNews("Yo")
时,indiaNews
观察者被告知 newsAgency
已更改。但没有被告知变化是什么。观察者可以使用 news
参数查看 newsAgency
的 当前 状态,但无法查看更改前的状态,或者确实更改后立即1.
在 Observer
/ Observable
的许多用例中,应用程序需要知道触发 update
调用的实际更改。
这是被强调的缺陷,也是弃用的 一个 原因。 javadocs 中的弃用文本还列出了其他内容:
"This class and the Observer
interface have been deprecated. The event model supported by Observer
and Observable
is quite limited, the order of notifications delivered by Observable
is unspecified, and state changes are not in one-for-one correspondence with notifications. For a richer event model, consider using the java.beans
package. For reliable and ordered messaging among threads, consider using one of the concurrent data structures in the java.util.concurrent
package. For reactive streams style programming, see the Flow
API."
1 - 由于未指定通知传递的顺序,观察对象的状态可能在 update
呼叫发生。
你的例子太简单了,因为它的特点是一个对象恰好有一个 属性 经历了一个状态变化。
当一个对象有多个 属性 时,事情会变得复杂得多。但也有可能状态变化不能直接表达为简单的 属性,例如“用户点击 (x,y)”。
并不是说 API 不允许传递必要的信息,因为源可以传递任意对象,它可以是包含所有必要信息的事件对象。但是由于此参数的类型为 Object
并且 Java 1.1 没有泛型来声明特化同时保持二进制兼容,因此这样的对象只是源和接收者之间的约定。您将不得不研究文档以找出您可以期待的内容。
Java1.1 中的 Java Beans 事件模型解决了这些问题。信息通过不同的机制传递
- 按类型。传递鼠标事件时,我们不需要遍历已注册的
KeyListener
s。
- 通过方法。通过调用
mousePressed
而不是 mouseReleased
,MouseListener
隐含地知道发生了什么。
- 通过键入的事件对象。
mousePressed
方法接收一个 MouseEvent
包含关于按钮的信息,坐标,还有是否,例如。同时按下了shift键。
无法将 Observable
/Observer
机制改造为新的设计模式,因此它只能被搁置,被遗忘。
但是,由于某种原因,它没有被标记为弃用。
缺少这样的标记或重定向到事件机制/Java Beans 模式导致人们仍在尝试使用它并因缺陷而绊倒,浪费了开发时间,而 JDK 开发人员实际认为结案:
错误 JDK-4180466,于 1998 年提交,报告缺少序列化支持。当 base class 不可序列化时,尝试在 subclass 中添加序列化支持会将存储和恢复观察者的责任转移到 subclass,但没有 API查询当前注册的观察者。
1999 年的回应是
This class is no longer under active development. It is largely unused in
the JDK, and has, for the most part, been superseded by the 1.1 Beans/AWT
event model.
请注意,两周后提交的错误 JDK-4212311 指出 API 文档与实际行为相矛盾,notifyObservers()
应该在通知观察者,但在 通知观察者之前调用 clearChanged()
。
Sun 没有人关心,如前所述,API 实际上已被放弃,既没有固定行为,也没有调整文档来说明该方法的实际作用。终于在 2016 年,在弃用 Observable
/Observer
的过程中,它被关闭为“不会修复”。
但是人们一直在这个 API 上浪费时间,因为它的文档没有告诉他们不要使用它。
喜欢2002年提交的JDK-4687908建议Observable
应该是一个接口。这是正确的,但无关紧要,因为它的继任者确实允许将事件源定义为接口。
或者JDK-8025077迟到2013年提交,担心这个废弃的API.
中没有文档化的线程安全策略
而这些都是人们最终提交错误报告的例子,我们只能推测有多少人事后没有提交报告是白费力气。
换句话说,问题不应该是,为什么 Observable
/Observer
被弃用,而是为什么花了二十年才停止维护这些 classes 将此信息添加到文档中。
然而,文档中给出的弃用原因相当奇怪。已弃用的警告声明“未指定 Observable
传递的通知顺序,并且状态更改不在 one-for-one 与通知 对应”,而是停留在鼠标事件通知示例,使用 multi-caster 的 AWT 组件也不保证特定的通知顺序,一般而言,侦听器不应假定特定的顺序。此外,移动事件支持合并,因此我们不能假设“one-for-one 与通知对应”并且不清楚为什么这应该是一个目标,尤其是一个如此重要以至于有理由弃用的目标。
我认为,弃用标记的文本应该是上面引用的内容:
This class is no longer under active development. It is largely unused in the JDK, and has, for the most part, been superseded by the 1.1 Beans/AWT event model.
也许
This class has blatant bugs and design flaws which were not fixed for two decades now.
而不是推理“通知顺序”、“one-for-one 通信”,或者它是否确实“传达了有关更改内容的任何信息”。
Check this by open jdk
deprecate Observer and Observable
Observer 和 Observable Class:
可观察到:-
class NewsAgency extends Observable {
String news;
public void setNews(String news) {
this.news = news;
setChanged();
notifyObservers(news);
}
}
观察者:-
public class IndiaNews implements Observer {
@Override
public void update(Observable o, Object news) {
System.out.println("Indianews: " +news.toString());
}
}
class AjjTak implements Observer {
@Override
public void update(Observable o, Object news) {
System.out.println("AjjTak: " +news.toString());
}
主要CLass:-
public class Main {
public static void main(String[] args) {
NewsAgency newsAgency = new NewsAgency();
IndiaNews indiaNews = new IndiaNews();
AjjTak ajjTak = new AjjTak();
newsAgency.addObserver(indiaNews);
newsAgency.addObserver(ajjTak);
newsAgency.setNews("Yo");
}
}
但是我能够告诉观察者消息已经改变 那么上面的说法怎么是真的呢?
谁能帮我理清思路?
谢谢:)
But I was able to tell the observer that news has changed then. How that above statement is true?
issue tracker link 中的文字说:
"For example, they support only the notion that something has changed, but they don't convey any information about what has changed."
在您的示例中,update
方法调用告诉观察者发生了一些变化,但实际上并没有发生变化。因此,当您调用 setNews("Yo")
时,indiaNews
观察者被告知 newsAgency
已更改。但没有被告知变化是什么。观察者可以使用 news
参数查看 newsAgency
的 当前 状态,但无法查看更改前的状态,或者确实更改后立即1.
在 Observer
/ Observable
的许多用例中,应用程序需要知道触发 update
调用的实际更改。
这是被强调的缺陷,也是弃用的 一个 原因。 javadocs 中的弃用文本还列出了其他内容:
"This class and the
Observer
interface have been deprecated. The event model supported byObserver
andObservable
is quite limited, the order of notifications delivered byObservable
is unspecified, and state changes are not in one-for-one correspondence with notifications. For a richer event model, consider using thejava.beans
package. For reliable and ordered messaging among threads, consider using one of the concurrent data structures in thejava.util.concurrent
package. For reactive streams style programming, see theFlow
API."
1 - 由于未指定通知传递的顺序,观察对象的状态可能在 update
呼叫发生。
你的例子太简单了,因为它的特点是一个对象恰好有一个 属性 经历了一个状态变化。
当一个对象有多个 属性 时,事情会变得复杂得多。但也有可能状态变化不能直接表达为简单的 属性,例如“用户点击 (x,y)”。
并不是说 API 不允许传递必要的信息,因为源可以传递任意对象,它可以是包含所有必要信息的事件对象。但是由于此参数的类型为 Object
并且 Java 1.1 没有泛型来声明特化同时保持二进制兼容,因此这样的对象只是源和接收者之间的约定。您将不得不研究文档以找出您可以期待的内容。
Java1.1 中的 Java Beans 事件模型解决了这些问题。信息通过不同的机制传递
- 按类型。传递鼠标事件时,我们不需要遍历已注册的
KeyListener
s。 - 通过方法。通过调用
mousePressed
而不是mouseReleased
,MouseListener
隐含地知道发生了什么。 - 通过键入的事件对象。
mousePressed
方法接收一个MouseEvent
包含关于按钮的信息,坐标,还有是否,例如。同时按下了shift键。
无法将 Observable
/Observer
机制改造为新的设计模式,因此它只能被搁置,被遗忘。
但是,由于某种原因,它没有被标记为弃用。
缺少这样的标记或重定向到事件机制/Java Beans 模式导致人们仍在尝试使用它并因缺陷而绊倒,浪费了开发时间,而 JDK 开发人员实际认为结案:
错误 JDK-4180466,于 1998 年提交,报告缺少序列化支持。当 base class 不可序列化时,尝试在 subclass 中添加序列化支持会将存储和恢复观察者的责任转移到 subclass,但没有 API查询当前注册的观察者。
1999 年的回应是
This class is no longer under active development. It is largely unused in the JDK, and has, for the most part, been superseded by the 1.1 Beans/AWT event model.
请注意,两周后提交的错误 JDK-4212311 指出 API 文档与实际行为相矛盾,notifyObservers()
应该在通知观察者,但在 通知观察者之前调用 clearChanged()
。
Sun 没有人关心,如前所述,API 实际上已被放弃,既没有固定行为,也没有调整文档来说明该方法的实际作用。终于在 2016 年,在弃用 Observable
/Observer
的过程中,它被关闭为“不会修复”。
但是人们一直在这个 API 上浪费时间,因为它的文档没有告诉他们不要使用它。
喜欢2002年提交的JDK-4687908建议Observable
应该是一个接口。这是正确的,但无关紧要,因为它的继任者确实允许将事件源定义为接口。
或者JDK-8025077迟到2013年提交,担心这个废弃的API.
中没有文档化的线程安全策略而这些都是人们最终提交错误报告的例子,我们只能推测有多少人事后没有提交报告是白费力气。
换句话说,问题不应该是,为什么 Observable
/Observer
被弃用,而是为什么花了二十年才停止维护这些 classes 将此信息添加到文档中。
然而,文档中给出的弃用原因相当奇怪。已弃用的警告声明“未指定 Observable
传递的通知顺序,并且状态更改不在 one-for-one 与通知 对应”,而是停留在鼠标事件通知示例,使用 multi-caster 的 AWT 组件也不保证特定的通知顺序,一般而言,侦听器不应假定特定的顺序。此外,移动事件支持合并,因此我们不能假设“one-for-one 与通知对应”并且不清楚为什么这应该是一个目标,尤其是一个如此重要以至于有理由弃用的目标。
我认为,弃用标记的文本应该是上面引用的内容:
This class is no longer under active development. It is largely unused in the JDK, and has, for the most part, been superseded by the 1.1 Beans/AWT event model.
也许
This class has blatant bugs and design flaws which were not fixed for two decades now.
而不是推理“通知顺序”、“one-for-one 通信”,或者它是否确实“传达了有关更改内容的任何信息”。