双向 Bean 同步
如何实现两个绑定属性之间的双向同步?实用程序类 PropertyChangeSupport 提供了一种避免无限循环的简单机制。在某些情况下,我发现它还不够。有更好的选择吗?
采用具有字符串边界属性的最简单的类:
private String myProperty;
//obviuos getter and setter omitted. (ok, setter contains propertyChangeSupport.firePropertyChange. should be obvious the same)
public void addPropertyChangeListener(PropertyChangeListener listener) {
//delegate to propertyChangeSupport
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
//delegate to propertyChangeSupport
}
好的。 现在,我尝试使用通知来执行此属性值之间的双向同步化,该属性值由此类的两个实例拥有。
这是(非常简单的)代码:
public static void main(String [] args) {
final T01 o1 = new T01();
final T01 o2 = new T01();
o1.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
o2.setMyProperty(o1.getMyProperty());
}
});
o2.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
o1.setMyProperty(o2.getMyProperty());
}
});
o1.setMyProperty("test");
}
这里没有无限循环,因为 PropertyChangeSupport当它返回到原始类时抑制通知,因为 oldValue 等于 newValue。
恕我直言,这是一个“微不足道”的实现,而更好的原则可能是“不应将事件通知给导致该事件的类”。
这种基于“等值”的实现存在的问题是:
1. 向更改的原始类引发不必要的冗余事件(然后原始类会抑制该事件)
2. 当旧值等于新值时,如果它是新值而不是“回头”值,则抑制该事件。在大多数情况下,抑制是正确的,但在某些(罕见)情况下,该事件可能是有用的。本身就是“信息丰富”的。考虑每次收到事件时都必须清除的超时。
3.它有一个“奇怪”的实现。如果你这样做:
o1.setMyProperty(null); <br/>
你会得到无限循环和随之而来的堆栈溢出。
因为如果值等于且不为空,则事件将被抑制。但在许多情况下“null”是合法的值。
How to implement bidirectional sinchronization between two bound properties? The utility class PropertyChangeSupport provides a trivial mechanism that avoids infinite loop. In some cases I find it to be insufficient. Is there a better alternative?
Take the simplest possible class with a String bounded property:
private String myProperty;
//obviuos getter and setter omitted. (ok, setter contains propertyChangeSupport.firePropertyChange. should be obvious the same)
public void addPropertyChangeListener(PropertyChangeListener listener) {
//delegate to propertyChangeSupport
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
//delegate to propertyChangeSupport
}
ok.
Now I try to use notifications in order to perform bidirectional sincronization between this property value, owned by two instances of this class.
This is the (quite simple) code:
public static void main(String [] args) {
final T01 o1 = new T01();
final T01 o2 = new T01();
o1.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
o2.setMyProperty(o1.getMyProperty());
}
});
o2.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
o1.setMyProperty(o2.getMyProperty());
}
});
o1.setMyProperty("test");
}
Here there is no infinite loop, because the PropertyChangeSupport suppress the notification when it turns back to the originating class, because the oldValue is equal than the newValue.
IMHO this is a "trivial" implementation, while a better principle may be that "an event should NOT be notified to the class that has caused it".
The problems with this implementation based on "equal values" are:
1. raises a unnecessary, redundant event to the originating class of the change (that THEN the originating class suppresses)
2. suppresses the event when the oldvalue equals newvalue also if it is a new one and not a "turning back" one. In most cases the suppression is correct, but in some (rare) cases the event may however be useful. Be itself "informative". Think to a timeout that has to be cleared each time an event is received.
3. it has a "strange" implementation. If you do:
o1.setMyProperty(null); <br/>
you get the infinite loop and the consequent stackoverflow.
Because the event is suppressed if the values are equals AND not null. But "null" is in many cases a legitimate value.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以尝试 jGoodies 绑定库 和 jGoodies 绑定库 jarvana.com/jarvana/view/com/jgoodies/binding/2.0.6/binding-2.0.6-javadoc.jar!/com/jgoodies/binding/beans/PropertyConnector.html" rel="nofollow">PropertyConnector:
现在
o1
的绑定属性myProperty
将与o2
同步,反之亦然。You can try jGoodies Binding Library and the PropertyConnector:
Now the bound property
myProperty
ofo1
will be synchronized witho2
and vice versa.