在MVC中通知观察者的最佳方式?

时间:2009-08-07 17:45:06

标签: model-view-controller design-patterns

假设某个View感兴趣的模型中有5个或6个变量,您是否为每个变量编写了不同的函数,例如

int a;
int b;
int c;

void setA( newA ) {
   a = newA;
   notifyAObservers();
}

void setB( newB ) {
   b = newB;
   notifyBObservers();
}

void setC( newC ) {
   b = newC;
   notifyCObservers();
}

或者你只有一个通知方法并浪费一点CPU时间

即。而不是notifyAObservers和notifyBObservers,你只需要notifyObservers

2 个答案:

答案 0 :(得分:6)

我相信traditional approach会通知所有观察者,并让他们处理它。这是因为您不知道哪些观察者正在观察哪个变量 - 您只知道他们希望在出现变化时收到通知。但是,如果您确实知道观察者正在观察哪些变量,并且性能至关重要,那么您可能会做出类似的事情。

在传统的Observer模式中,Observers实现了一个update()方法,当发生更改时,控制器会调用该方法。 Observables(数据模型)将有一个notifyObservers()方法,它迭代Observers并调用它们的update()方法。然后,观察者得到他们需要的东西并且视图更新。

但是,只要我实现了Observer模式,我只需保留一个观察者列表并通知所有人。这样,我只有一个观察者列表,其余的类以及不同的观察者都可以改变,而不会对可观察的类通知进行任何更改。

答案 1 :(得分:0)

编辑:几年前我写了我的答案。刚读完之后,我觉得我需要更新它。

我认为最好的方法是通知所有观察者并让观点决定他们是否需要自我更新。

每个视图都能够验证模型的状态并采取相应的行动。 此外,“args”可用作标志以指示已更改的内容(视图可能不希望每次更改都更新自己。)

这样,模型REALLY不知道视图的显示方式和内容,它们是分离的。

第一个实现看起来像这样:

public class MyModelV1 extends Observable {
    private int value;
    public void setValue(int value) {
        this.value = value;
        setChanged();
        notifyObservers();
    }
    public int getValue() {
        return value;
    }
}
public class MyViewV1 implements Observer {
    public void update(Observable o, Object arg) {
        if (o instanceof MyModelV1) {
            System.out.println(((MyModelV1) o).getValue());
        }
    }
}

视图只检查收到的observable的类型。 但是,如果模型具有许多属性并触发许多不同场景的视图,则此简单检查可能会过于频繁地刷新视图。

另一种方法如下:

public class MyModelV2 extends Observable {
    private int value;
    public void setValue(int value) {
        this.value = value;
        setChanged();
        notifyObservers("value");
    }
    public int getValue() {
        return value;
    }
}
public class MyViewV2 implements Observer {
    public void update(Observable o, Object arg) {
        if (o instanceof MyModelV2 && "value".equals(arg)) {
            System.out.println(((MyModelV2) o).getValue());
        }
    }
}

此处,通知传递限定符,使视图更准确地决定何时刷新自身。 视图仍然需要检查并转换模型,因为没有保证arg“value”不会被另一个模型通知(并且转换会在运行时失败)。

我个人的最爱是这样的:

public class MyModelV3 extends Observable {
    private int value;
    public void setValue(int value) {
        this.value = value;
        setChanged();
        Notification.MY_MODEL_VALUE_UPDATED.notifyObserver(this);
    }
    public int getValue() {
        return value;
    }
}
public class MyViewV3 implements Observer {
    public void update(Observable o, Object arg) {
        if (Notification.MY_MODEL_VALUE_UPDATED.equals(arg)) {
            MyModelV3 model = Notification.MY_MODEL_VALUE_UPDATED.getModel(o);
            System.out.println(model.getValue());
        }
    }
}
public class Notification<T extends Observable> {
    public static final Notification<MyModelV3> MY_MODEL_VALUE_UPDATED = new Notification<MyModelV3>();
    private Notification() {
    }
    public T getModel(Observable o) {
        return (T) o;
    }
    public void notifyObserver(T observable){
        observable.notifyObservers(this);
    }
}

此处,通知发送一个强类型限定符,该限定符绑定到Model。 视图可以使用通知来检索强类型模型(而不是强制转换)。

这是在观察者和事件总线之间的某个地方。