观察者模式

Author Avatar
丁起男 06月 22,2021
  • 在其它设备中阅读本文章

观察者模式

需求

天气预报

  • 气象站可以将每天测量到的温度、湿度、气压等等以公告的形式发布出去
  • 需要设计开放型api,便于其他第三方也能接入气象站获取数据
  • 提供温度、气压、湿度的接口
  • 测量数据更新时,要能实时通知给第三方

普通方案

接入方

//显示天气情况(可以理解成网站)
public class CurrentCoditions{
    //温度、气压、湿度
    private float temperature;
    private float pressure;
    private float humidity;
    
    //更新,是由WeatherData调用(推送)
    public void update(float temperature,float pressure,float humidity){
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }
    
    //显示
    public void display(){
        System.out.println(temperature);
        System.out.println(pressure);
        System.out.println(humidity);
    }
}

数据提供方

/**
* 核心
* 包含最新的天气情况信息
* 含有CurrentConditions对象
* 当数据有更新时,就主动调用currentConditions的upate方法,这样接入方就看到了最新信息
*/
@Data
public class WeatherData{
    private float temperatrue;
    private float pressure;
    private float humidity;
    private CurrentConditions currentConditions;
    
    public WeatherData(CurrentConditions currentConditions){
        this.currentConditions = currentConditions;
    }
    //推送
    public void dataChange(){
        currentConditions.update(temperatrue,pressure,humidity);
    }
    //数据更新
    public void setData(float temperatrue,float pressure,float humidity){
        this.temperatrue = temperatrue;
        this.pressure = pressure;
        this.humidity = humidity;
        dataChange();
    }
}

使用

//接入方
CurrentCoditions currentCoditions = new CurrentCoditions();
//提供方
WeatherData weatherData = new WeatherData(currentCoditions);
//更新数据
weatherData.setData(10.0f,10.0f,10.0f);
//更新数据
weatherData.setData(20.0f,20.0f,20.0f);

问题分析

  • 其他第三方无法接入
  • 无法运行时动态的添加第三方
  • 违反了开闭原则(ocp)

观察者模式

对象之间多对一依赖的一种设计方案。被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化

被依赖对象接口

public interface Subject{
    //注册
    public void registerObserver(Observer o);
    //删除
    public void removeObserver(Observer o);
    //通知
    public void notifyObserver();
}

观察者接口

public interface Observer{
    //数据改变
    public void update(float temperatrue,float pressure,float humidity);
}

接入方,实现观察者接口

//显示天气情况(可以理解成网站)
public class CurrentCoditions implements Observer{
    //温度、气压、湿度
    private float temperature;
    private float pressure;
    private float humidity;
    
    //更新,是由WeatherData调用(推送)
    @Override
    public void update(float temperature,float pressure,float humidity){
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }
    
    //显示
    public void display(){
        System.out.println(temperature);
        System.out.println(pressure);
        System.out.println(humidity);
    }
}

数据提供方,实现被依赖对象接口

/**
* 核心
* 包含最新的天气情况信息
* 含有Observer观察者集合
* 当数据有更新时,就主动调用currentConditions的upate方法,这样接入方就看到了最新信息
*/
@Data
public class WeatherData implements Subject{
    private float temperatrue;
    private float pressure;
    private float humidity;
    private List<Observer> observers;
    
    public WeatherData(){
        observers = new ArrayList();
    }

    //数据更新
    public void setData(float temperatrue,float pressure,float humidity){
        this.temperatrue = temperatrue;
        this.pressure = pressure;
        this.humidity = humidity;
        //推送给观察者
        notifyObserver();
    }
    
    @Override
    public void registerObserver(Observer o){
        observers.add(o);
    }
    @Override
    public void removeObserver(Observer o){
        observers.remove(o);
    }
    @Override
    public void notifyObserver(){
        for(Observer observer : observers){
            observer.update(temperatrue,pressure,humidity);
        }
    }
}

使用

//被依赖对象
Subject subject = new WeatherData();
//观察者
Observer observer = new CurrentCoditions();
//注册
subject.registerObserver(observer);
//修改
subject.setData(10.0f,10.0f,10.0f);