设计模式之观察者模式

观察者模式

定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

体现新的OO原则: 为交互对象之间的松耦合设计而努力。

类图:

  1. 主题接口
public interface Subject {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObserver();
}
  1. 观察者接口
public interface Observer {
    public void updata(float temp, float humidity, float pressure);
}
  1. 具体主题
public class WeatherData implements Subject {

    private ArrayList observers;

    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData(){
        observers = new ArrayList();
    }

    public void measurementsChanged(){
        notifyObserver();
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }

    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if (i >= 0){
            observers.remove(i);
        }
    }

    @Override
    public void notifyObserver() {
        for (int i = 0; i < observers.size(); i++){
            Observer observer = observers.get(i);
            observer.updata(temperature, humidity, pressure);
        }
    }
}
  1. 具体观察者
public class CurrentConditionsDisplay implements Observer {

    private float temperature;
    private float humidity;
    private Subject weartherData;

    public CurrentConditionsDisplay(Subject weartherData) {
        this.weartherData = weartherData;
        //注册
        weartherData.registerObserver(this);
    }

    @Override
    public void updata(float temp, float humidity, float pressure) {
        this.temperature = temp;
        this.humidity = humidity;
        //do something
    }
}

当然关于观察者模式,还存在”拉”和”推”一说,其实上面的例子就是”推”的例子,可以在一次通知中得到所有东西,上面的例子就是在一次通知将温度(temp)、湿度(humidity)和气压(pressure)全部得到,如果采用”拉”的方式就是三个get和set方法,每次可以”拉”走你需要的状态。

java 内置观察者模式

使用 java.util.Observable 和 java.util.Observer 实现观察者。可以使用推push或拉pull的方式传送数据。

类图:

  1. 可观察者
import java.util.Observable;

public class MWeatherData extends Observable {
    private float temperature;
    private float humidity;
    private float pressure;

    public MWeatherData(){}

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }

    public void measurementsChanged(){
        //在调用notifyObservers之前,需要先调用setChanged指示状态以改变
        setChanged();
        //没有在参数里面传递数据,表示观察者自己拉数据
        notifyObservers();
    }

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }
}
  1. 具体观察者
import java.util.*;

public class MCurrentConditionDisplay implements java.util.Observer {

    Observable observable;
    private float temperature;
    private float humidity;

    public MCurrentConditionDisplay(Observable observable) {
        this.observable = observable;
        observable.addObserver(this);
    }

    @Override
    public void update(Observable observable, Object data) {
        if (observable instanceof MWeatherData){
            MWeatherData mWeatherData = (MWeatherData) observable;
            this.temperature = mWeatherData.getTemperature();
            this.humidity = mWeatherData.getHumidity();
            //do something
        }
    }
}

注意:

  1. java.util.Observable 的实现有许多问题,限制了它的使用和复用。
  2. Observable 是一个类,不是一个接口,java是只支持单继承的,限制了Observable的复用。
  3. Observable 中 setChanged() 方法时 protected 的。