• head first 设计模式笔记2-观察者模式:气象观测站


    设计原则:为了交互对象之间的松耦合设计而努力。

    1、设计模式的一些理解

      1)知道OO基础,并不足以让你设计出良好的OO系统

      2)良好的OO设计必须具备可复用、可扩充、可维护三个特性

      3)模式可以让我们建造出具有良好OO设计质量的系统

      4)模式被认为是历经验证的OO设计经验

      5)模式不是代码,而是针对设计问题的通用解决方案。你可把它们应用到特定的应用中

      6)模式不是被发明,而是被发现

      7)大多数的模式和原则,都着眼于软件变化的主题

      8)大多数的模式都允许系统局部改变独立于其他部分

      9)我们常把系统中会变化的部分抽出来封装

         10)模式让开发人员之间有共享的语言,能够最大化沟通的价值

    2、观察者模式:气象观测站

      需求:建立一个下一代Internet气象观测站。该气象站必须建立再我们专利申请中的WeatherData对象上,由WeatherData对象负责追踪目前的天气状况(温度/湿度、气压)。我们希望贵公司能建立一个应用,有三种布告板,分别显示目前的状况、气象统计及简单的预报。当WeatherData对象获得最新的测量数据时,三种布告板必须实时更新。

      而且,这是一个可以扩展的气象站,Weather-O-Rama气象站希望公布一组API,好让其他开发人员可以写出自己的气象布告板,并插入此应用中。我们希望贵公司能提供这样的API。

      气象监测应用的概况:此系统中的三个部分是气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看)。WeatherData对象知道如何跟物理气象站联系,以取得更新的数据。WeatherData对象会随即更新三个布告板的显示:目前状况(温度、湿度、气压)、气象统计和天气预报。

      我们的工作:建立一个应用,利用WeatherData对象取得数据,并更新三个布告板:目前状况、气象统计和天气预报。

       认识观察者模式:举例报纸和杂志的订阅

      1)报社的业务就是出版报纸。

      2)向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,你就会一直收到新报纸。

      3)当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸来。

      4)只要报社还在运营,就会一直有人向他们订阅报纸或取消订阅报纸。

       出版者 + 订阅者  = 观察者模式,出版者叫做“主题”(Subject), 订阅者叫做"观察者"(Observer)

      

      观察者模式定义:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

      观察者模式,类图设计:

       Subject

    public interface Subject {
        public void registerObserver(Observer o);
        public void removerObserver(Observer o);
        // 当主题状态改变时,这个方法会被调用,以通知所有的观察者
        public void notifyObservers();
    }

      Observer

    public interface Observer {
        public void update(float temp, float humidity, float pressure);
    }

      DisplayElement

    public interface DisplayElement {
        public void display();
    }

       WeatherData

    public class WeatherData implements Subject {
        private ArrayList observers;
        private float temperature;
        private float humidity;
        private float pressure;
    
        public WeatherData() {
            observers = new ArrayList();
        }
        
        @Override
        public void registerObserver(Observer o) {
            observers.add(o);
        }
    
        @Override
        public void removerObserver(Observer o) {
            int i = observers.indexOf(o);
            if (i >= 0) {
                observers.remove(i);
            }
        }
    
        @Override
        public void notifyObservers() {
            for (int i = 0; i < observers.size(); i ++) {
                Observer observer = (Observer) observers.get(i);
                observer.update(temperature, humidity, pressure);
            }
        }
        
        /**
         * 当从气象站得到更新观测值时,通知观察者
         */
        public void measurementsChanged() {
            notifyObservers();
        }
        
        /**
         * 测试时用这个方法来更新数据
         * @param temperature
         * @param humidity
         * @param pressure
         */
        public void setMeasurements(float temperature, float humidity, float pressure) {
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
            measurementsChanged();
        }
    
        public float getTemperature() {
            return temperature;
        }
        public float getHumidity() {
            return humidity;
        }
        public float getPressure() {
            return pressure;
        }
    }

       CurrentConditionsDisplay

    public class CurrentConditionsDisplay implements Observer, DisplayElement {
        private float temperature;
        private float humidity;
        private Subject weatherData;
        
        public CurrentConditionsDisplay(Subject weatherData) {
            this.weatherData = weatherData;
            weatherData.registerObserver(this);
        }
    
        @Override
        public void display() {
            System.out.println("Current conditions: " + temperature+ "F degrees and "
                    + humidity + "% humidity");
        }
    
        @Override
        public void update(float temp, float humidity, float pressure) {
            this.temperature = temp;
            this.humidity = humidity;
            display();
        }
    }

       测试代码:

    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
        
        // 模拟新的气象测量:一旦气象数据更新就会主动"推送"给每个观察者
        weatherData.setMeasurements(80, 65, 30.4f);
        weatherData.setMeasurements(82, 70, 29.2f);
        weatherData.setMeasurements(78, 90, 30.0f);
        
        // 观察者主动"拉"数据
        System.out.println("观察者主动"拉"数据");
        currentConditionsDisplay.update(weatherData.getTemperature(), 
                weatherData.getHumidity(), weatherData.getPressure());
    }

    3、使用jdk提供的观察者相关类 java.util.Observable(主题),java.util.Observer(观察者)

      WeatherData

    import java.util.Observable;
    
    /**
     * @author oy
     * @date 2019年8月25日 下午8:44:06
     * @version 1.0.0
     */
    public class WeatherData extends Observable {
        private float temperature;
        private float humidity;
        private float pressure;
        
        public WeatherData() {}
            
        public void measurementsChanged() {
            setChanged();
            // 我们没有调用nodifyObservers()传送数据对象,表示我们采用的做法是"拉"
            notifyObservers();
        }
        
        public void setMeasurements(float temperature, float humidity, float pressure) {
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
            measurementsChanged();
        }
    
        public float getTemperature() {
            return temperature;
        }
        public float getHumidity() {
            return humidity;
        }
        public float getPressure() {
            return pressure;
        }
    }

      DisplayElement

    public interface DisplayElement {
        public void display();
    }

      CurrentConditionsDisplay

    import java.util.Observable;
    import java.util.Observer;
    
    /**
     * @author oy
     * @date 2019年8月25日 下午10:34:19
     * @version 1.0.0
     */
    public class CurrentConditionsDisplay implements Observer, DisplayElement {
        Observable observable;
        private float temperature;
        private float humidity;
        
        public CurrentConditionsDisplay(Observable observable) {
            this.observable = observable;
            observable.addObserver(this);
        }
        
        @Override
        public void display() {
            System.out.println("Current conditions: " + temperature  + "F degrees and "
                    + humidity + "% humidity");
        }
    
        @Override
        public void update(Observable obs, Object arg) {
            if (obs instanceof WeatherData) {
                WeatherData weatherData = (WeatherData)obs;
                this.temperature = weatherData.getTemperature();
                this.humidity = weatherData.getHumidity();
                display();
            }
        }
    }

      测试代码

    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        weatherData.setMeasurements(80, 65, 30.4f);
        
        // 创建观察者,并注册
        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
        // 主动pull数据
        currentDisplay.update(weatherData, null);
        
        // 更新数据,push数据给观察者
        weatherData.setMeasurements(78, 90, 30.0f);
        // 当然,观察者主动pull数据
        //currentDisplay.update(weatherData, null);
    }

      注意:

  • 相关阅读:
    关于“云计算”
    实现工作流至少需要几张表?
    BPI (业务流程改进)项目的管理沙龙笔记
    对“设计”工作在流程中的重新定位
    面向。。。驱动
    定个小目标
    Redis源码分析Sentinel(1)Sentinel服务器
    Redis源码分析Sentinel(3)主观下线与客观下线
    Redis源码分析Sentinel(2)实例处理的Monitor half
    Redis源码分析Sentinel(4)实例处理的Acting half
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/11380613.html
Copyright © 2020-2023  润新知