[英]Using method references as listeners with observer pattern
the usage of method references as listeners in an observer pattern does not work.在观察者模式中使用方法引用作为监听器是行不通的。 Example:
例子:
public class ObserverWithMethodReferenceAsListenerTest {
class ListenerCurator {
private final Set<Consumer<String>> listeners = new HashSet<>();
public boolean register(final Consumer<String> consumer) {
return this.listeners.add(consumer);
}
public boolean unregister(final Consumer<String> consumer) {
return this.listeners.remove(consumer);
}
public int getListenersCount() {
return this.listeners.size();
}
}
class MyListenerLeaks {
public void theListener(final String someString) {
// the listener
}
}
class MyListenerWorks {
public Consumer<String> consumer = str -> {
theListener(str);
};
public void theListener(final String someString) {
// the listener
}
}
@Test
public void testListenerLeak() {
ListenerCurator lc = new ListenerCurator();
MyListenerLeaks ml = new MyListenerLeaks();
lc.register(ml::theListener);
Assert.assertEquals(1, lc.getListenersCount());
lc.register(ml::theListener);
// expected 1 but there are 2 listeners
lc.unregister(ml::theListener);
// there are 2 listeners registered here
}
@Test
public void testListenerWorks() {
ListenerCurator lc = new ListenerCurator();
MyListenerWorks ml = new MyListenerWorks();
lc.register(ml.consumer);
Assert.assertEquals(1, lc.getListenersCount());
lc.register(ml.consumer);
Assert.assertEquals(1, lc.getListenersCount());
lc.unregister(ml.consumer);
Assert.assertEquals(0, lc.getListenersCount());
}
}
Conclusion: each referencing of the listener method with ml::theListener generates a new object id for the reference?结论:每次使用 ml::theListener 引用监听器方法都会生成一个新的 object id 以供引用? Right?
正确的? Therefore there a multiple listeners registered and cannot be removed individually?
因此,注册了多个侦听器并且不能单独删除?
The MyListenerWorks class uses a member with a "constant" object id and works. MyListenerWorks class 使用具有“常量” object id 的成员并工作。 Is there another workaround for this?
还有其他解决方法吗? Are my assumptions correct?
我的假设是否正确?
From the Oracle documentation on Method References:来自关于方法参考的 Oracle 文档:
Method references enable you to do this;
方法引用使您能够做到这一点; they are compact, easy-to-read lambda expressions for methods that already have a name.
它们是紧凑的、易于阅读的 lambda 表达式,用于已经有名称的方法。
A method reference is not a constant .方法引用不是常量。
After I added some breakpoints to the HashSet#add and remove function. I got some results for your questions in the images below:在我向 HashSet#add 和 remove function 添加了一些断点之后。我在下图中得到了一些针对您的问题的结果:
1. each referencing of the listener method with ml::theListener generates a new object id for the reference? 1. 每次使用 ml::theListener 引用监听器方法都会生成一个新的 object id 作为引用? Right?
正确的?
Ans: No. It would generate a new memory address into the HashSet. Ans:不会。它会在 HashSet 中生成一个新的 memory 地址。 There would not be an object id.
不会有 object id。 So in the test function:testListenerLeak, you cannot remove the listener correspondingly.
所以在测试function:testListenerLeak中,不能对应的去掉监听。 Since you didn't get the listeners from the set before you remove it.
因为在删除它之前你没有从集合中得到听众。
2. The MyListenerWorks class uses a member with a "constant" object id and works. 2. MyListenerWorks class 使用具有“常量”object id 的成员并工作。 Is there another workaround for this?
还有其他解决方法吗? Are my assumptions correct?
我的假设是否正确?
You could take a look of the Observer pattern in Spring, Vue, or some other famous project.你可以看看 Spring、Vue 或其他一些著名项目中的观察者模式。 they have something similar to what you want.
他们有类似于你想要的东西。 But mostly I have ever read about this pattern is in the Event-driven model. They use the "instanceOf" to check the subclasses and their superclass.
但我读过的关于这种模式的大部分内容是在事件驱动的 model 中。他们使用“instanceOf”来检查子类及其超类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.