zoukankan      html  css  js  c++  java
  • 【设计模式】观察者模式

    一、简介

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

    有很多项目都用到了该设计模式,比如Spring的事件机制、消息队列等。
    Java提供了两个接口java.util.Observablejava.util.Observer,也可以利用这两个接口实现。

    类图如下:

     

    观察者模式类图
    观察者模式类图

     

    二、示例

    需求背景是气象站发布天气数据,所有订阅了气象站的布告板显示天气数据。
    先上类图:

     

    enter description here
    enter description here

    主题接口

     

    /**
     * 主题接口
     * Created by 2YSP on 2018/1/24.
     */
    public interface Subject {
        /**
         * 注册一个观察者
         * @param observer
         */
         void registerObserver(Observer observer);
    
        /**
         * 移除一个观察者
         * @param observer
         */
         void removeObserver(Observer observer);
    
        /**
         * 通知所有观察者
         */
         void notifyObservers();
    }
    

    观察者接口

    public interface Observer {
        /**
         * 所有观察者必须实现该方法,
         * 当气象观测值改变时,主题会把这些状态值当参数传给观察者
         * @param temp
         * @param humidity
         * @param pressure
         */
         void update(float temp,float humidity,float pressure);
    }
    

    具体主题WeatherData

    public class WeatherData implements Subject {
        /**
         * 注册的观察者集合
         */
        private List<Observer> observers;
        /**
         * 温度
         */
        private float temperature;
        /**
         * 湿度
         */
        private float humidity;
        /**
         * 气压
         */
        private float pressure;
    
        public WeatherData(){
            observers = new ArrayList();
        }
    
        @Override
        public void registerObserver(Observer observer) {
            observers.add(observer);
        }
    
        @Override
        public void removeObserver(Observer observer) {
            if (observers.contains(observer)){
                observers.remove(observer);
            }
        }
    
        @Override
        public void notifyObservers() {
            observers.forEach(o -> {
                o.update(temperature,humidity,pressure);
            });
        }
    
        public void measurementsChanged(){
            notifyObservers();
        }
    
        public void setMeasurements(float temperature,float humidity,float pressure){
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
            measurementsChanged();
        }
    
        //WeatherData的其他方法
    }
    

    当前状况布告板,这里只弄了一个,还可以根据自己的需求定义其他种类的布告板。

    /**
     * 当前状况布告板(还可以建立其他观察者)
     * Created by 2YSP on 2018/1/24.
     */
    public class CurrentConditionDisplay implements Observer,DisplayElement {
        /**
         * 温度
         */
        private float temperature;
        /**
         * 湿度
         */
        private float humidity;
    
        private Subject weatherData;
    
        public CurrentConditionDisplay(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();
        }
    }
    

    DisplayElement

    public interface DisplayElement {
        /**
         * 布告板显示气象数据
         */
        void display();
    }
    

    气象站

    public class WeatherStation {
    
        public static void main(String[] args) {
            WeatherData weatherData = new WeatherData();
            CurrentConditionDisplay currentCondition = new CurrentConditionDisplay(weatherData);
    
            weatherData.setMeasurements(80,65,30.4f);
        }
    }
    

    运行main方法控制台输出如下,说明布告板收到了消息并自动更新。

    Current conditions: 80.0F degrees and 65.0% humidity

    注意: 这里是通过构造方法传入具体主题,然后调用具体主题的registerObserver(Observer observer) 方法来实现注册观察者的。在实际项目中,我们可以通过在spring的xml配置文件上配置进行观察者的注册,这样更加灵活,不用修改代码。需要给WeatherData添加一个setObservers(List observers) 方法,利用set方法注入。

            <bean id="weatherData" class="xx.xx.WeatherData">
                <property name="observers">
                    <list>
                        <ref bean="currentConditionDisplay"/>
                    </list>
                </property>
            </bean>
    
  • 相关阅读:
    zend studio常见问题解答
    瀑布流插件(jquery.masonry.js)
    仿jQuery中undelegate()方法功能的函数
    Linux 常用命令
    linux debugfs 找回rm 的文件
    jq 添加和移除样式
    CentOS 搭建 nginx python django web server
    Linux vim 配置文件
    CentOS 安装python 3.3.2
    login.defs和shadow文件区别
  • 原文地址:https://www.cnblogs.com/2YSP/p/11602078.html
Copyright © 2011-2022 走看看