尚硅谷设计模式-观察者模式


笔记来源:尚硅谷

一、需求

天气预报项目需求,具体要求如下:

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

二、解决方案

2.1 普通方案

  1. 网站调用的气象站dataChange()

  2. 当数据定时更新时,气象站数据更新后,调用网站的update(),推送到网站

    //可以理解成气象站自己的网站
    public class CurrentConditions {
        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("***Today mTemperature:" + temperature +"***");
            System.out.println("***Today mPressure: " + pressure + "***");
            System.out.println("***Today mHumidity: " + humidity + "***");
        }
    }
    
    /**
     *  1.包含最新的天气信息
     *  2. 含有CurrentConditions对象
     *  3. 当数据更新时,主动调用update
     */
    public class WeatherData {
    	private float temperatrue;
    	private float pressure;
    	private float humidity;
    	private CurrentConditions currentConditions;
    
    	public WeatherData (CurrentConditions currentConditions) {
    		this.currentConditions = currentConditions ;
    	}
    
    	/*省略get set*/
        
    	public void dataChange() {
            //调用网站update方法
    		currentConditions.update(getTemperatrue(), getPressure(), getHumidity());
    	}
    	
        //当数据更新时调用setData,更新WeatherData
        public void setData(float temperatrue, float pressure, float humidity){
            this.humidity = humidity;
            this.pressure = pressure;
            this.temperatrue = temperatrue;
            //推送最新数据给网站
            dataChange();
        }
    	
    }
    

    调用过程如下:

    public class Client {
    	public static void main(String[] args) {
    		//创建接入方currentConditions
    		CurrentConditions currentConditions = new CurrentConditions();
    		//创建WeatherData并将接入方currentConditions传递到WeatherData中
    		WeatherData weatherData = new WeatherData(currentConditions);
    		//更新天气情况
    		weatherData.setData(30, 150, 40);
    	}
    }
    

问题分析:

当添加多个第三方时,会修改WeatherData类中的大量方法,不利于维护,不能动态添加

2.2 观察者模式

观察者模式类似于订牛奶业务

  1. 奶站/气象局:Subject – 登记,注册,移除,通知
  2. 用户/第三方网站:Observer – 接受输入方,有更新方法

➢观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer, Subject通知Observer变化,比如这里的奶站Subject,是1的一方。用户时Observer,是多的一方。

public interface Subject {
	public void registerObserver (Observer o);
	public void remove0bserver (observer o);
	public void notifyObservers();
}
//观察者接口,由观察者实现
public interface Observer {
	public void update(float temperatrue, float pressure, float huminity );
}
//百度,实现观察者接口
public class Baidu implements Observer {

	private float temperature;
	private float pressure;
	private float humidity;

	public void display() {
		System.out.println("***Today mTemperature:" + temperature +"***");
		System.out.println("***Today mPressure: " + pressure + "***");
		System.out.println("***Today mHumidity: " + humidity + "***");
	}

	@Override
	public void update(float temperature, float pressure, float humidity) {
		this.temperature = temperature;
		this.pressure = pressure;
		this.humidity = humidity;
		display();
	}
}
/**
 *  1.包含最新的天气信息
 *  2. 含有 观察者集合
 *  3. 当数据更新时,通知所有接入方,让他们看到最新消息
 */
public class WeatherData implements Subject{
    private float temperature;
    private float pressure;
    private float humidity;
    private List<Observer> observers;

    public WeatherData () {
        this.observers = new ArrayList<Observer>();
    }

    /*省略get set*/

    @Override
    public void registerObserver(Observer o) {
        observers.add(o);

    }

    @Override
    public void remove0bserver(Observer o) {
        observers.remove(o);

    }

    @Override
    public void notifyObservers() {
        for(Observer observer : observers) {
            observer.update(temperature, pressure, humidity);
        }		
    }

    public void setData(float temperatrue, float pressure, float humidity){
        this.humidity = humidity;
        this.pressure = pressure;
        this.temperature = temperatrue;
        notifyObservers();
    }
}

调用时可以动态添加观察者,可维护性大大增强

posted @ 2020-07-08 21:08  衍射  阅读(209)  评论(0编辑  收藏  举报