Я думаю, что у вас есть 2 общие параметры
- пусть клиентский код явно отключить уведомления
- инкапсулировать изменения в собственном классе и использовать метод шаблона
Давайте посмотрим на оба варианта. Для моих примеров я буду использовать простой Observer
.
public class StdoutObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("Observable changed: " + o);
}
}
код клиента явно отключает уведомления
public class MyClass<E> extends Observable {
private ArrayList<E> items = new ArrayList<E>();
private boolean changing;
public void setIsChanging(boolean changing){
this.changing = changing;
if(!changing && hasChanged()){
notifyObservers();
}
}
public void add(E e) {
this.items.add(e);
notifyChanged();
}
public void remove(E e) {
if (this.items.remove(e)) {
notifyChanged();
}
}
private void notifyChanged(){
setChanged();
if(!changing){
notifyObservers();
}
}
}
и клиентский код выглядит следующим образом
MyClass<String> stringMyClass = new MyClass<String>();
stringMyClass.addObserver(new StdoutObserver());
System.out.println("setting changing: true");
stringMyClass.setIsChanging(true);
stringMyClass.add("C");
stringMyClass.add("D");
stringMyClass.add("E");
System.out.println("setting changing: false");
stringMyClass.setIsChanging(false);
выход будет
setting changing: true
setting changing: false
Observable changed: [email protected]
Проблема с этим решением заключается в том, что код клиента может забыть включить уведомления (или сообщить наблюдаемым, что изменения сделаны). В этом случае уведомления могут быть отключены навсегда.
Инкапсулируйте изменения в собственном классе и использовать метод шаблона
Определить интерфейс для отображения изменений
public interface ObservableChange<T extends Observable> {
public void doChange(T observable);
}
вашего Observable
затем будет использовать метод шаблона для того, чтобы changing
состояния сбрасывается при выполнении изменения.
public class MyClass<E> extends Observable {
private ArrayList<E> items = new ArrayList<E>();
private boolean changing;
public void update(ObservableChange<MyClass2<E>> observableChange) {
setIsChanging(true);
try {
observableChange.doChange(this);
} finally {
setIsChanging(false);
}
}
private void setIsChanging(boolean changing) {
this.changing = changing;
if (!changing && hasChanged()) {
notifyObservers();
}
}
public void add(E e) {
this.items.add(e);
notifyChanged();
}
public void remove(E e) {
if (this.items.remove(e)) {
notifyChanged();
}
}
private void notifyChanged() {
setChanged();
if (!changing) {
notifyObservers();
}
}
}
Клиентский код будет выглядеть следующим образом;
MyClass<String> stringMyClass = new MyClass<String>();
stringMyClass.addObserver(new StdoutObserver());
stringMyClass.update(new ObservableChange<MyClass<String>>() {
@Override
public void doChange(MyClass<String> observable) {
observable.add("A");
observable.add("B");
observable.add("C");
observable.add("D");
}
});
и выход будет
Observable changed: [email protected]
Используя метод шаблона гарантирует, что уведомления только отключены до тех пор, как изменения сделаны, потому управления наблюдателями это.
В этом случае я считаю, что лучший способ - создать два метода deleteAll и addAll, чтобы вы уведомили наблюдателей в конце операции. –