设计模式真香笔记-观察者模式

观察者模式的介绍

观察者模式:对象之间一对多依赖,当一个对象改变状态的时候,它的所有依赖都会收到通知并且自动更新。
这样说可能有些人不能理解,我们来举个生动形象的例子:

许多人以前会经常订阅杂志,杂志社会定期发杂志给订阅者,当然他也可以取消订阅,那么杂志社就不会继续发杂志给订阅者。

这个例子里面杂志社就是可观察者,而订阅者就相当于观察者,杂志社定期更新会通知他的所有依赖也就是订阅者。
再来个图促进理解:
观察者模式

利用到的新原则

  • 为交互对象之间的松耦合设计而努力

观察者模式的例子(气象台布告板例子)

UML类图

有空在画图。

实现代码附带一些解释

  • Subject接口
/**
 * Subject接口为可观察者(主题)接口
 * @
 */
public interface Subject {
     /**
      * @param o 传入参数为观察者接口实现对象
      */
     void registerObserver(Observer o);//注册为观察者
     void removeObserver(Observer o);//退出观察者
     void notifyObserevers();//当主题数据改变时及时候通知观察者。
}
  • Observer接口
public interface Observer {//观察者接口
    void update(float temperature, float humidity,float pressure);//更新数据
}

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

  • WeatherData(实现可观察接口成为可观察者)
public class WeatherData implements Subject {
    private ArrayList observers;
    private float temperature;//温度
    private float humidity;//湿度
    private float pressure;//气压
    public WeatherData(){
        observers = new ArrayList();//用于观察者注册的集合
    }
    @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 notifyObserevers() {
        for (Object observer: observers
             ) {
            Observer observer1 = (Observer) observer;
            observer1.update(temperature,humidity,pressure);

        }
    }
    public void measurementsChanged(){//更新通知
        notifyObserevers();
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {//改变观察者数据
        this.temperature=temperature;
        this.humidity=humidity;
        this.pressure=pressure;
        measurementsChanged();
    }
    //其他扩展方法
}
  • CurrentConditionDisplay (实现观察者接口成为观察者)
public class CurrentConditionDisplay implements  Observer,Display {
    private float temperature;
    private float humidity;
    private Subject weatherData;
    public CurrentConditionDisplay(Subject weatherData){//构造方法实现注册为观察者
        this.weatherData=weatherData;
        weatherData.registerObserver(this);
    }

    @Override
    public void display() {//显示数据
        System.out.println("CurrentConditionDisplay:"+temperature+"Humidity"+humidity);
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
            this.temperature=temperature;
            this.humidity=humidity;
            display();
    }
}
  • CurrentConditionDisplayM(实现观察者接口成为观察者)
public class CurrentConditionDisplayM implements  Observer,Display {
    private float temperature;
    private float humidity;
    private float pressure;
    private Subject weatherData;
    public CurrentConditionDisplayM(Subject weatherData){
        this.weatherData=weatherData;
        weatherData.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("CurrentConditionDisplayM:"+temperature*3+"Humidity"+humidity/2+"pressure"+pressure*4);
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature=temperature;
        this.humidity=humidity;
        this.pressure=pressure;
        display();
    }
}
  • WeatherStation(气象站类也就是测试类)
public class WeatherStation {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
       CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);
        CurrentConditionDisplayM currentConditionDisplayM = new CurrentConditionDisplayM(weatherData);
        weatherData.setMeasurements(80,68,29.2f);
       weatherData.setMeasurements(90,100,23);

    }
}
  • 打印结果
    观察者模式打印结果

观察者模式的总结

可观察者和观察者之间用松耦合的形式结合,可观察者只知道观察者实现了观察者的接口,而不知道观察者具体内容。
有多个观察者时候,不可以依赖特定的通知次序。
swing类库中就有很多使用观察者模式的例子,譬如说:点击按钮添加多种监听器,实现不同的功能。

一些补充

在java.util 类库中有实现好的观察者模式。Observable.java(可观察者类是类不是接口),在这类里面有一个setchanged()方法用来标记可观察者的状态的事实,那他的意义是什么呢?我们不需要标记就可以更新啊,其实他的作用是为了控制可观察者的更新频率,我们可以通过这个方法实现上面的气象站例子 三天,或者半个月更新一次,没有这个方法,我们没有办法控制,气象站就会实时更新。具体我们可以java.util类库中Observable.java的源码。


本文参考:《Head First 设计模式》

原文地址:https://www.cnblogs.com/narojay/p/10812599.html