观察者模式

作者: imyyq_star | 来源:发表于2018-01-03 09:50 被阅读11次

    需求

    监听天气数据,一旦数据改变,则更新布告板的内容。数据有:温度、湿度、气压

    被观察者,也称为主题,Observable,(Subject)

    /**
     * 主题接口,所有主题接口都应该实现此接口
     */
    public interface Subject
    {
        /**
         * 注册观察者
         */
        public void registerObserver(Observer o);
    
        /**
         * 删除观察者
         */
        public void removeObserver(Observer o);
    
        /**
         * 当主题状态改变的时候,会调用此方法,通知所有的观察者
         */
        public void notifyObservers();
    }
    
    
    /**
     * 处理气象站数据的类,实现了主题Subject接口,用来接收气象站的信息,并通知所有的观察者
     */
    public class WeatherData implements Subject
    {
        // 用来记录观察者
        private ArrayList<Observer> observers = new ArrayList<Observer>();
    
        private float temperature;
        private float humidity;
        private float pressure;
    
        public void registerObserver(Observer o)
        {
            observers.add(o);
        }
    
        public void removeObserver(Observer o)
        {
            observers.remove(o);
        }
    
        /**
         * 把状态告诉每一个观察者,观察者们都实现了update方法,所有我们知道如何通知他们
         */
        public void notifyObservers()
        {
            for (Observer observer : observers)
            {
                observer.update(temperature, humidity, pressure);
            }
        }
    
        /**
         * 当气象站数据更新的时候,此方法被调用
         */
        public void measurementsChanged()
        {
            notifyObservers();
        }
    
        /**
         * 由于是模拟气象站,因此通过此方法模拟气象站调用measurementsChanged()方法
         */
        public void setMeasurements(float temperature, float humidity,
                float pressure)
        {
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
            measurementsChanged();
        }
    
        // 省略 get
    }
    

    观察者(Observer)与布告板

    /**
     * 观察者接口,所有观察者都应该实现此接口
     */
    public interface Observer
    {
        /**
         * 所有的观察者都必须实现的方法,当主题状态变化时,调用此方法
         * 
         * @param temp      温度
         * @param humidity  湿度
         * @param pressure  气压
         */
        public void update(float temp, float humidity, float pressure);
    }
    
    
    /**
     * 布告板接口,所有的气象布告板都需要实现此接口
     */
    public interface DisplayElement
    {
        /**
         * 当布告板需要显示时,调用此方法
         */
        public void display();
    }
    
    
    /**
     * 状况布告板
     */
    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);
        }
    
        /**
         * 当主题状态变化时,调用此方法
         */
        public void update(float temperature, float humidity, float pressure)
        {
            this.temperature = temperature;
            this.humidity = humidity;
            // 显示布告板,设置数据的显示方式,可以有很多方式,比如MVC
            display();
        }
    
        /**
         * 当布告板需要显示时,调用此方法
         */
        public void display()
        {
            System.out.println("Current conditions: " + temperature
                    + "F degrees and " + humidity + "% humidity");
        }
    }
    

    测试

    public static void main(String[] args)
    {
        // 建立气象站数据处理类对象
        WeatherData weatherData = new WeatherData();
    
        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(
                weatherData);
        // StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
        // ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
        // HeatIndexDisplay heatIndexDisplay = new HeatIndexDisplay(weatherData);
    
        weatherData.setMeasurements(80, 65, 30.4f);
        weatherData.setMeasurements(82, 70, 29.2f);
        weatherData.setMeasurements(78, 90, 29.2f);
    }
    

    观察者模式的定义:

    定义了对象间的一对多依赖,当一个对象状态改变时,所以依赖者都会收到通知并自动更新
    

    设计原则 4

    让交互对象松耦合,降低对象的互相依赖,彼此不知道对方的细节,但是可以交互。

    观察者:Observer

    被观察者:Observable,(Subject)

    订阅报纸的例子

    Java 也有内置的观察者模式

    应用了哪些设计原则

    • 组合:观察者是通过运行时注册到被观察者的
    • 针对接口:观察者和被观察者都是实现了对应的接口,注册和通知都是接口来进行的,松耦合
    • 抽出会改变的部分,和不变的分开来:被观察者的状态会改变,观察者的数量和类型会改变,但是被观察者本身不用变,只需要关注各自状态的改变

    注意

    观察者被通知的次序是未知的

    相关文章

      网友评论

        本文标题:观察者模式

        本文链接:https://www.haomeiwen.com/subject/bxzcnxtx.html