• 观察者模式


    天气预报需求

    一个天气预报的项目,需求如下:

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

    传统方案

    1. 初步设计一个WeatherData类,包含getTemperature、getHumidity、getPressure、dataUpdate四个方法
    2. 通过getXXX来获取不同信息,气象站通过调用dataUpdate来更新数据,当第三方再次获取就能得到最新数据,或者主动给第三方推送
    /***
     * @author shaofan
     * @Description 传统方案解决天气预报需求
     */
    public class WeatherForecast {
        public static void main(String[] args) {
            WeatherCondition weatherCondition = new WeatherCondition();
            WeatherData weatherData = new WeatherData(weatherCondition);
            weatherData.setData(1,1,1);
            System.out.println(weatherCondition);
            weatherData.setData(2,2,2);
            System.out.println(weatherCondition);
        }
    }
    
    /***
     * 第三方天气信息
     */
    class WeatherCondition{
        private float temperature;
        private float pressure;
        private float humidity;
    
        public void update(WeatherData weatherData){
            this.temperature = weatherData.getTemperature();
            this.pressure = weatherData.getPressure();
            this.humidity = weatherData.getHumidity();
        }
    
        @Override
        public String toString() {
            return "WeatherCondition{" +
                    "temperature=" + temperature +
                    ", pressure=" + pressure +
                    ", humidity=" + humidity +
                    '}';
        }
    }
    
    /***
     * 气象站天气信息
     */
    class WeatherData{
        private float temperature;
        private float pressure;
        private float humidity;
        private WeatherCondition weatherCondition;
    
        public WeatherData(WeatherCondition weatherCondition){
            this.weatherCondition = weatherCondition;
        }
        public float getTemperature() {
            return temperature;
        }
    
        public float getPressure() {
            return pressure;
        }
    
        public float getHumidity() {
            return humidity;
        }
    
        /**
         * 气象站更新第三方的天气
         */
        private void weatherUpdate(){
            weatherCondition.update(this);
        }
    
        /**
         * 气象站检测到天气更新
         * @param temperature
         * @param pressure
         * @param humidity
         */
        public void setData(float temperature,float pressure,float humidity){
            this.temperature =temperature;
            this.pressure = pressure;
            this.humidity = humidity;
            weatherUpdate();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    问题分析

    新增一个第三方,都需要创建一个新的第三方对象,并加入都dataChange中,不利于维护,也不是动态加入

    观察者模式

    1. 被订阅方看作一个Subject,可以在这个Subject上面注册Observer观察者,Subject维护registerObserver、removeObserver、notifyObservers方法
    2. 观察者模式是对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化;Subject是1的一方、Observer是多的一方

    观察者模式解决天气预报问题

    在这里插入图片描述

    /***
     * @author shaofan
     * @Description 观察者模式解决天气预报问题
     */
    public class WeatherForecast {
        public static void main(String[] args) {
            WeatherData weatherData = new WeatherData();
            WeatherCondition weatherCondition = new WeatherCondition();
            weatherData.registerObserver(weatherCondition);
            weatherData.setData(1,1,1);
            System.out.println(weatherCondition);
        }
    }
    
    /***
     * 被订阅方
     */
    interface Subject{
        void registerObserver(Observer observer);
        void removeObserver(Observer observer);
        void notifyObservers();
    }
    
    /***
     * 观察者
     */
    interface Observer{
        void update(WeatherData weatherData);
    }
    
    class WeatherData implements Subject{
        private float temperature;
        private float pressure;
        private float humidity;
        private List<Observer> observers;
        public WeatherData(){
            observers = new ArrayList<>();
        }
    
        public float getTemperature() {
            return temperature;
        }
    
        public float getPressure() {
            return pressure;
        }
    
        public float getHumidity() {
            return humidity;
        }
    
        @Override
        public void registerObserver(Observer observer) {
            this.observers.add(observer);
        }
    
        @Override
        public void removeObserver(Observer observer) {
            this.observers.remove(observer);
        }
    
        @Override
        public void notifyObservers() {
            for (Observer observer : this.observers) {
                observer.update(this);
            }
        }
    
        public void setData(float temperature,float pressure,float humidity){
            this.temperature =temperature;
            this.pressure = pressure;
            this.humidity = humidity;
            notifyObservers();
        }
    }
    
    class WeatherCondition implements Observer{
        private float temperature;
        private float pressure;
        private float humidity;
        @Override
        public void update(WeatherData weatherData) {
            this.temperature = weatherData.getTemperature();
            this.pressure = weatherData.getPressure();
            this.humidity = weatherData.getHumidity();
        }
    
        @Override
        public String toString() {
            return "WeatherCondition{" +
                    "temperature=" + temperature +
                    ", pressure=" + pressure +
                    ", humidity=" + humidity +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96

    源码分析

    jdk中Observeable类,使用了观察者模式
    在这里插入图片描述

    1. Observable的作用等价于Subject,这里没有Subject抽象
    2. Observable已经实现了核心的方法,即管理Observer的方法
    3. Observer的地位和常规写法的Observer相同
  • 相关阅读:
    Nginx配置文件及Nginx服务优化
    【CKA考试笔记】六、存储管理
    mysql查询速度 limit 1000,10 和limit 10 一样快吗?
    Vue基础与常用指令,Element基础
    C语言描述数据结构 —— 栈和队列
    thrift的简单使用
    windows设置自启动服务使用winsw
    window.eventBus 在Vue中的使用方法(二)定义全局事件——$emit之触发事件传参 & $on-接收事件参数 & $off-移除事件
    C# 实例解释面向对象编程中的里氏替换原则
    MySQL学习第二部分:事务的理解
  • 原文地址:https://blog.csdn.net/m0_48468380/article/details/126522728