zoukankan      html  css  js  c++  java
  • 观察者模式的理解和使用

    一、是什么?作用

    1. 观察者模式定义了一系列对象之间的一对多关系

    2. 当一个对象改变状态, 其他依赖着都会受到通知

    二、示例

    需求: 气象观测天气,并定时更新观测数据,我们的电子仪器需要接受这些数据

    1. PUSH模式, 由被观察者推送给观察者

    1. 定义主题, 即被观察者

    /**
     * 主题
     */
    public interface Subject {
    
        // 添加观察者
        void registerObserver(Observer o);
    
        // 删除观察者
        void removeObserver(Observer o);
    
        // 通知
        void notifyObservers();
    }

    2. 定义观察者的超类,里面只有一个更新的方法

    /**
     * 观察者超类
     */
    public interface Observer {
    
        public void update(float temp, float humidity, float pressure);
    }

    3. 天气数据, 主题的子类

      1. 有一个属性来存放观察者

      2. 实现主题的方法

      3. 有三个数据需要传递(温度、湿度、气压)

     1 /**
     2  * 天气数据, 实现主题
     3  */
     4 public class WeatherData implements Subject {
     5 
     6     /**
     7      * 存储观察者
     8      */
     9     private List<Observer> observers;
    10     private float temperature;
    11     private float humidity;
    12     private float pressure;
    13 
    14     public WeatherData() {
    15         this.observers = new ArrayList<>();
    16     }
    17 
    18     /**
    19      * 当气象站得到更新观测值时,我们通知观察者
    20      */
    21     public void measurementsChanged() {
    22         notifyObservers();
    23     }
    24 
    25     /**
    26      * 模拟气象站更改了气象数据
    27      */
    28     public void setMeasurements(float temperature, float humidity, float pressure) {
    29         // 更改气象数据
    30         this.temperature = temperature;
    31         this.humidity = humidity;
    32         this.pressure = pressure;
    33 
    34         // 通知观察者
    35         measurementsChanged();
    36     }
    37 
    38     @Override
    39     public void registerObserver(Observer o) {
    40         observers.add(o);
    41     }
    42 
    43     @Override
    44     public void removeObserver(Observer o) {
    45         int i = observers.indexOf(0);
    46         if (i >= 0) {
    47             observers.remove(0);
    48         }
    49     }
    50 
    51     @Override
    52     public void notifyObservers() {
    53         for (Observer observer : observers) {
    54             observer.update(temperature, humidity, pressure);
    55         }
    56     }
    57 
    58     public float getTemperature() {
    59         return temperature;
    60     }
    61 
    62     public float getHumidity() {
    63         return humidity;
    64     }
    65 
    66     public float getPressure() {
    67         return pressure;
    68     }
    69 }

    4. 观察者具体类, 实现观察者,将主题通过构造传入,并订阅(这里将耦合度降到了很低了),实现更新方法

    /**
     * 显示当前天气的仪器 - 观察者的具体类
     */
    public class NowConditionDisplay implements Observer {
        private float temperature;
        private float humidity;
        private WeatherData weatherData;
    
        public NowConditionDisplay(WeatherData weatherData) {
            this.weatherData = weatherData;
            weatherData.registerObserver(this);
        }
    
        @Override
        public void update(float temp, float humidity, float pressure) {
            this.temperature = temp;
            this.humidity = humidity;
            display();
        }
    
        public void display() {
            System.out.println("[push] 当前温度:" + temperature + " 当前湿度: " + humidity);
        }
    }

    测试

    public class pushMain {
    
        public static void main(String[] args) {
            WeatherData weatherData = new WeatherData();
            NowConditionDisplay nowConditionDisplay = new NowConditionDisplay(weatherData);
    
            weatherData.setMeasurements(20, 10, 29.2f);
        }
    }
    
    
    控制台显示:
    [push] 当前温度:20.0 当前湿度: 10.0

    2. PULL模式, 由观察者去拉数据

    1. 天气数据提供者,利用java.util包下的Observable类来实现

    import java.util.Observable;
    
    /**
     * 数据提供者
     */
    public class WeatherData extends Observable {
    
        // 三个数据
        private float temperature;
        private float humidity;
        private float pressure;
    
        public WeatherData() {
        }
    
        public void measurementChanged() {
            setChanged();
            notifyObservers();
        }
    
        public void setMeasurements(float temperature, float humidity, float pressure) {
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
    
            measurementChanged();
        }
    
        public float getTemperature() {
            return temperature;
        }
    
        public float getHumidity() {
            return humidity;
        }
    
        public float getPressure() {
            return pressure;
        }
    }

    2. 观察者子类, 实现java.util的Observer 

    import java.util.Observable;
    import java.util.Observer;
    
    /**
     * @author wb-xp570304 on 2019/7/9
     */
    public class NowConditionDisplay implements Observer {
    
        Observable observable;
        private float temperature;
        private float humidity;
    
        public NowConditionDisplay(Observable observable) {
            this.observable = observable;
            observable.addObserver(this);
        }
    
        @Override
        public void update(Observable o, Object arg) {
            if (o instanceof WeatherData) {
                WeatherData weatherData = (WeatherData) o;
                this.temperature = weatherData.getTemperature();
                this.humidity = weatherData.getHumidity();
                display();
            }
        }
    
        public void display() {
            System.out.println("当前温度: " + temperature + " 湿度: " + humidity);
        }
    }

    测试:

    public class pullMain {
    
        public static void main(String[] args) {
            WeatherData weatherData = new WeatherData();
    
            NowConditionDisplay nowConditionDisplay = new NowConditionDisplay(weatherData);
    
            weatherData.setMeasurements(80, 65, 30f);
        }
    }

    控制台显示:
      当前温度: 80.0 湿度: 65.0

    小结: 

      第二种pull的方式这里是利用java.util.Observable来实现的,而且用的是继承,减少了代码的可扩展性

    三、总结

     1. 观察者模式的理念是,为交互对象之间的松耦合设计而努力

  • 相关阅读:
    949. Largest Time for Given Digits
    450. Delete Node in a BST
    983. Minimum Cost For Tickets
    16. 3Sum Closest java solutions
    73. Set Matrix Zeroes java solutions
    347. Top K Frequent Elements java solutions
    215. Kth Largest Element in an Array java solutions
    75. Sort Colors java solutions
    38. Count and Say java solutions
    371. Sum of Two Integers java solutions
  • 原文地址:https://www.cnblogs.com/milicool/p/11189629.html
Copyright © 2011-2022 走看看