设计模式之观察者模式

观察者者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,所有的依赖者都会收到通知并及时更新。
举一个气象观察站的例子:假如有一个气象站可以检测温度,湿度,气压,现在要把这些数据全部传送到三块显示板上,气象站是一,三块显示板是多,最容易想到的方案是定义一个气象站类WeatherData,在类里面写一个方法,把数据分别传送给三个显示板,如下所示:

public class WeatherData {
    //实例变量声明
    public void measurementChanged() {
        //取得最近的测量值
        float temp = getTemplature();
        float humidity = getHumidity();
        float pressure = getPressure();        
        //更新显示板
        currentConditionsDisplay.update(temp, humidity, pressure);
        statisticsDisplay.update(temp, humidity, pressure);
        forecastDisplay.update(temp, humidity, pressure);
    }
}

上面的方式是针对的具体实现编程,所以如果要增加显示板或者减少显示板,那么上面的程序就要修改,显示板和气象站耦合在一起,这样不利于扩展。下面利用观察者模式来解决这个问题。

//主题接口
public interface Subject {
    public void registerObserver(Observer o);    //注册观察者
    public void removeObserver(Observer o);        //移除观察者
    public void notifyObservers();                //通知观察者
}

//观察者接口
public interface Observer {
    public void update(float temp, float humidity, float pressure);    //更新数据
}

//显示数据接口
public interface DisplayElement{
    public void display();
}

//气象站
public class WeatherData implements Subject {
    private ArrayList observers;    //保存观察者的ArrayList
    private float temperature;
    private float humidity;
    private float pressure;

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

    public void registerObserver(Observer o) {    //添加观察者
        observers.add(o);
    }

    public void removeObserver(Observer o) {    //移除观察者
        int i = observers.indexOf(o);
        if (i >= 0) {
            observers.remove(i);
        }
    }

    public void notifyObservers() {                //通知观察者
        for (int i = 0; i < observers.size(); i++ ) {
            Observer observer = (Observer)observers.get(i);
            observer.update(temperature, humidity, pressure);
        }
    }

    public void measurementChanged() {            //数据改变时通知观察者
        notifyObservers();
    }
}

//观察者
public class CurrentConditionsDisplay implements Observer, DisplayElement {
    private float temperature;
    private float humidity;
    private Subject weatherData;    //每个观察者都有一个主题接口

    public CurrentConditionsDisplay (Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        display();
    }

    public void display() {
        System.out.println("Current conditions:" + temperature + "F degrees and" + humidity + "%humidity");
    }
}

这样,当我们要扩展程序增加观察者时,只需写一个实现了Observer, DisplayElement接口的类就可以了,原程序不需要改动。




原文地址:https://www.cnblogs.com/fengz/p/6748443.html