观察者模式

来源:互联网 发布:js 字符串转数组 编辑:程序博客网 时间:2024/06/08 12:09

定义

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

这里写图片描述

以气象站更新气象信息为例

// 主题接口public interface SubJect {    void registerObserver(Observer o);    void removeObserver(Observer o);    void notifyObservers();}
// 气象站实现主题接口public class WeatherData implements SubJect {    // 气象信息:温度,湿度,气压    private String temperature;    private String humidity;    private String pressure;    // 观察者列表    private List<Observer> observers;    public WeatherData() {        this.observers = new ArrayList<Observer>();    }    @Override    public void registerObserver(Observer o) {        observers.add(o);    }    @Override    public void removeObserver(Observer o) {        if(observers.indexOf(o)>0){            observers.remove(o);        }    }    // 如何通知观察者,其实就是遍历本地的观察者列表,执行它们的update方法    @Override    public void notifyObservers() {        this.temperature = getTemperature();        this.humidity = getHumidity();        this.pressure = getPressure();        for(Observer o: observers){            o.update(temperature,humidity,pressure);        }    }    public String getTemperature() {        return temperature;    }    public String getHumidity() {        return humidity;    }    public String getPressure() {        return pressure;    }    /**     * 气温有变化时立即调用     */    public void measureChanged(){        notifyObservers();    }}
// 观察者接口public interface Observer {    void update(String temperature,String humidity,String pressure);}
// 这时一个气象统计布告,当气象信息变化时展示public class 气象统计 implements Observer{    // 本地气象信息    private String temperature;    private String humidity;    private String pressure;    // 主题对象,用来注册自己    private SubJect weatherData;    public 气象统计(SubJect weatherData) {        this.weatherData = weatherData;        // 初始化的时候注册自己        weatherData.registerObserver(this);    }    // 实现update方法,一旦气象信息变化了,主题会调用该方法    @Override    public void update(String temperature, String humidity, String pressure) {        this.temperature = temperature;        this.humidity = humidity;        this.pressure = pressure;        this.display();    }    @Override    public void display() {        System.out.println(toString());    }    @Override    public String toString() {        return "气象统计{" +                "temperature='" + temperature + '\'' +                ", humidity='" + humidity + '\'' +                ", pressure='" + pressure + '\'' +                '}';    }}

其实java内置了观察者模式,但是有些内容和上述略有不同,但是都是情理之中。下面一一解释

区别一:

jdk自带的观察者模式中,被观察者接口是Observer
Observer有方法setChanged(),是将一个全局变量变为true,为什么呢?

protected synchronized void setChanged() {        changed = true;    }

显然,当没有变的时候,是不更新的。那么“变”到底指的是什么?其实是对事实的控制,比如说温度,如果精确单位是千分之一,那岂不是温度时时刻刻都在变化,这样更新太频繁了。我们只有当它的温度变化超过一度,才会setChanged(),这时候才会真的通知所有观察者

public void notifyObservers(Object arg) {        Object[] arrLocal;        synchronized (this) {            if (!changed)                return;            arrLocal = obs.toArray();            clearChanged();        }        for (int i = arrLocal.length-1; i>=0; i--)            ((Observer)arrLocal[i]).update(this, arg);    }

区别二:update方法的参数,理应是Obj对象,而不是自定义的。

update有两个参数,一个是带个Observer的数据,一个是主题本身

@Override    public void update(Observable o, Object arg) {        if(o instanceof WeatherData){            this.temperature = ((WeatherData) o).getTemperature();            this.humidity = ((WeatherData) o).getHumidity();            this.pressure = ((WeatherData) o).getPressure();            display();        }    }
0 0