Как реализовать двунаправленную синхронизацию между двумя связанными свойствами?Служебный класс PropertyChangeSupport предоставляет тривиальный механизм, позволяющий избежать бесконечного цикла.В некоторых случаях я считаю, что этого недостаточно.Есть ли лучшая альтернатива?
Возьмем простейший из возможных классов с ограниченным свойством String:
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.Теперь я пытаюсь использовать уведомления, чтобы выполнить двунаправленную синхронизацию между значением этого свойства, принадлежащего двум экземплярам этого класса.
Это (довольно простой) код:
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/>
вы получаете бесконечный цикл и последующий стекопоток.Потому что событие подавляется, если значения равны И не ноль.Но «ноль» во многих случаях является законной ценностью.