深入理解23种设计模式(16) --观察者模式

介绍

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

在这里插入图片描述

  • Subject : 是主题,它把所有对观察者对象的引用文件存在了一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供了一个接口,可以增加和删除观察者对象
  • Observer : 是抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己
  • ConcreteSubject : 是具体主题,将有关状态存入具体观察者对象,在具体主题内部状态改变时,给所有登记过的观察者发出通知
  • ConcreteObserver : 是具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协同。

案例

  1. 气象站可以将每天测量到的温度,湿度,气压等以公告的形式发布出去(比如第三方平台)。
  2. 需要设计第三方API,便于第三方也能接入获取天气数据。
  3. 提供温度,湿度,气压接口
  4. 测量数据更新时,需要时实时通知给第三方

创建Subject 接口

public interface Subject {

    /**
     * 注册观察者
     */
    public void registerObserver(Observer observer);

    /**
     * 删除观察者
     */
    public void removeObserver(Observer observer);

    /**
     * 通知观察者
     */
    public void notifyObserver(float temperature, float pressure, float humidity);

}

创建ConcreteSubject 类实现 Subject接口

public class ConcreteSubject implements Subject {

    //储存订阅
    private List<Observer> observerList = new ArrayList<Observer>();

    @Override
    public void registerObserver(Observer observer) {
        observerList.add(observer);

    }

    @Override
    public void removeObserver(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyObserver(float temperature, float pressure, float humidity) {
        observerList.stream().forEach( bean -> {
            System.out.printf("通知订阅用户 :");
            bean.update(temperature,pressure,humidity);
        });
    }
}

创建 Observer 接口

public interface Observer {

    /**
     * 更新
     * @param temperature
     * @param pressure
     * @param humidity
     */
    public void update(float temperature,float pressure,float humidity);
}

创建 ConcrereObserver 类 实现Observer接口

public class ConcrereObserver implements Observer{


    private String name;

    public ConcrereObserver(String name) {
        this.name = name;
    }

    @Override
    public void update(float temperature, float pressure, float humidity) {
        CurrentCondition currentCondition = new CurrentCondition(name,temperature,pressure,humidity);
    }
}

当前温度实体类

@Data
public class CurrentCondition {

    private float temperature;

    private float pressure;

    private float humidity;

    public CurrentCondition(String name,float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        display(name);
    }

    private void display(String name) {
        System.out.println("用户"+name);
        System.out.println("Today :: 温度 :" + temperature);
        System.out.println("Today :: 湿度 :" + humidity);
        System.out.println("Today :: 气温 :" + pressure);
    }
}

客户端

public class Client {

    public static void main(String[] args) {
        Subject concreteSubject = new ConcreteSubject();
        ConcrereObserver concrereObserver = new ConcrereObserver("1");
        ConcrereObserver concrereObserver2 = new ConcrereObserver("2");
        concreteSubject.registerObserver(concrereObserver);
        concreteSubject.registerObserver(concrereObserver2);
        //通知用户
        concreteSubject.notifyObserver(1,1,1);


    }
}

在这里插入图片描述

优点和缺点

优点:

1)观察者模式后,会以集合的形式来管理用户(Observer), 包括注册、移除、通知
2)我们增加观察者,就不会去修改核心类的代码,保证来OCP原则
3)在同一个聚合上可以有多个遍历。 
4)在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。 

缺点:

 1)如果观察者和观察目标间有循环依赖,可能导致系统崩溃
 2)没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的

JDK中观察者的实现

public class Observable {
    private boolean changed = false;
    private Vector<Observer> obs;

    /** Construct an Observable with zero Observers. */

    public Observable() {
        obs = new Vector<>();
    }
	……
}

Observable 类就使用了类观察者模式,其中obs 就是存放用户的集合Vector 包含 Observer

private Vector<Observer> obs;


public interface Observer {
    /**
     * This method is called whenever the observed object is changed. An
     * application calls an <tt>Observable</tt> object's
     * <code>notifyObservers</code> method to have all the object's
     * observers notified of the change.
     *
     * @param   o     the observable object.
     * @param   arg   an argument passed to the <code>notifyObservers</code>
     *                 method.
     */
    void update(Observable o, Object arg);
}

在这里插入图片描述

  • Observable 相当于我们的Subject,Observable是类,不是接口,类中已经实现了方法(添加,删除,通知 等方法)
  • Observer 即观察者模式中的Observer,有update方法


github Demo地址 : ~~~传送门~~~

个人博客地址:http://blog.yanxiaolong.cn/

end
  • 作者:yxl(联系作者)
  • 发表时间:2021-02-22 15:10
  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 转载声明:如果是转载栈主转载的文章,请附上原文链接
  • 公众号转载:请在文末添加作者公众号二维码(公众号二维码见右边,欢迎关注)
  • 评论