我正在尝试将观察者模式应用于包含一组记录的类。
在 Java 伪代码中,我的类是:
public class MyClass<E> extends Observable
{
private ArrayList<E> items = new ArrayList<E>();
public MyClass()
{
}
public void add(E e)
{
this.items.add(e);
setChanged();
notifyObservers();
}
public void remove(E e)
{
if(this.items.remove(e))
{
setChanged();
notifyObservers();
}
}
...
}
我的问题是:在某些情况下,在程序执行期间,我必须在结构中进行大量删除和插入记录,并且出于性能目的,我希望观察者对象仅在整个操作结束时收到一次通知。
当然,我可以添加一些标志变量来处理对 setChanged
和 notifyObservers
的调用,但我想知道处理此类问题的“最佳”方法是什么.
所以我的问题:设计代码的最佳方法是什么,以便在对观察对象进行大规模修改后仅通知观察者对象一次?
最佳答案
我认为你有两个一般选择
- 让客户端代码显式禁用通知
- 将更改封装在自己的类中并使用模板方法
让我们看一下这两个选项。我将在示例中使用一个简单的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: MyClass@229ed927
此解决方案的问题是客户端代码可能会忘记启用通知(或告诉可观察对象更改已完成)。在这种情况下,通知可能会永远关闭。
将更改封装在自己的类中并使用模板方法
定义一个接口(interface)来表示更改
public interface ObservableChange<T extends Observable> {
public void doChange(T observable);
}
然后,您的Observable
将使用模板方法来确保更改完成后重置更改
状态。
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: MyClass2@33837697
使用模板方法可确保仅在更改完成后才禁用通知,因为观察者对此进行控制。
关于java - 可观察模式应用于海量记录更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37807102/