观察者模式

1、观察者模式的动机

建立一种一对多的依赖关系,一种发生变化时通知其他对象跟着做出反应。这种发生变化的对象称为主题或者被观察者,被通知做出相应的对象称为观察者。观察者相互 独立,允许添加,删除;

2、观察者模式的定义

定义了对象间的一对多的依赖,这样一来,当一个对象发生改变时,他的所有依赖均会收到通知并自行更新。
常用场景如:发布--订阅,模型--视图,源--监听者等;    

3、观察者模式的类结构图

image

模式中包含三个角色:主题类subject(接口或者抽象类),观察者接口observer,以及他们的具体实现类:

满足的设计原则如下:
1、为了交互对象的松耦合设计而努力
松耦合的的设计之所以能够让我们建立有弹性的oo系统,能够应对变化是因为对象之间的相互依赖降到了最低。 任何时候我们均可增加或减少观察者,而不必改变主题的代码,因为主题只依赖与观察者接口;相反,更改主题 代码时,而不会影响到观察者,因为观察者只依赖于主题接口的方法;所以只要他们均遵守接口约定,我们就可 以自由的改变他们;

2、针对接口编程,不针对实现编程 主题和观察者均使用接口,观察者利用主题接口方法注册对象,主题利用观察者接口方法通知观察者,这样两者 之间即可相互协作运行,也同时具备松耦合的有点;

3、多用组合,少用继承 观察者模式利用”组合”将许多观察者组合进主题中。对象之间不是通过继承产生这种关系,而是通过运行时利用 组合发方式而产生的;

4、封装变化 观察者模式中变化的是主题的状态,以及观察者的数目和类型,利用这个模式,可以改变依赖主题状态的对象,而 不必更改主题;

4、 优缺点和适用场景

优点:

缺点:

适用场景:

5、实例

例:气象监测,weatherData负责监测天气的气温,气压,温度等,每当监测到新的数据时,需要及时展示在多个展示 板上。
类图结构:
image

主题接口:

public interface Subject<T> {
    void registerObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObserver(T t);
}

天气预报实现类:

public class WeatherData implements Subject<Weather> {
    List<Observer> observerList = new ArrayList<Observer>();
    public void registerObserver(Observer observer) {
        observerList.add(observer);
    }

    public void removeObserver(Observer observer) {
        int index = observerList.indexOf(observer);
        if (index >= 0) {
            observerList.remove(index);
        }
    }

    public void notifyObserver(Weather weather) {
        for(Observer observer : observerList) {
            observer.updata(weather);
        }
    }

    public void measurementChange() {
        Weather weather = new Weather(12, 13, 14);
        notifyObserver(weather);
    }
}

观察者接口:

public interface Observer<T> {
    void updata(T t);
}

具体展示模板:

public class SecondDisplay implements Observer<Weather> {
    private Subject subject;

    public SecondDisplay(Subject subject) {
        this.subject = subject;
        subject.registerObserver(this);
    }

    public void updata(Weather weather) {
        System.out.println(this.getClass() + "输出天气预报:" + weather.toString());
    }
}
public class StaticsDisplay implements Observer<Weather> {
    private Subject subject;

    public StaticsDisplay(Subject subject) {
        this.subject = subject;
        subject.registerObserver(this);
    }

    public void updata(Weather weather) {
        System.out.println(this.getClass() + "输出天气预报:" + weather.toString());
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        // 实现并注册观察者
        new SecondDisplay(weatherData);
        new StaticsDisplay(weatherData);
        weatherData.measurementChange();
    }
}