美文网首页
设计模式之观察者模式

设计模式之观察者模式

作者: MVBin | 来源:发表于2017-05-23 11:23 被阅读25次

    观察者模式(Observer Pattern)

    观察者模式定义了对象之间的一对多依赖,当一个对象的状态改变时,它的所有依赖者都会收到通知并自动更新。该模式可以让主题和观察者之间松耦合,降低相互之间的依赖性。
    一个来自《Head First设计模式》的气象站实例


    /*
     * 一个Subject接口(主题接口):让实现该接口的所有类都具有以下三种方法,用于注册、删除、更新观察者
     *
     */
    public interface Subject {
        //注册一个观察者
        public void registerObserver(Observer ob);
        //注销一个观察者
        public void removeObserver(Observer ob);
        //当主题状态改变时,调用此方法,更新所有观察者
        public void notifyObservers();
    }
    
    /*
     * 一个Observer接口(观察者接口):实现该接口的类必须含有update()方法
     *
     */
    public interface Observer {
        //当气象观测值改变时,主题接口的实现类会把这些状态值作为参数传递给Observer接口实现类的update()方法
        public void update(float temperature, float humidity, float pressure);
    }
    
    /*
     * 一个DiaplayElement接口
     */
    public interface DisplayElement {
        //用于显示天气信息
        public void display();
    }
    
    public class WeatherData implements Subject {
    
        //天气信息的三个属性
        private float temperature;//温度
        private float humidity;//湿度
        private float pressure;//气压
    
        private List<Observer> obs;
    
        //构造方法
        public WeatherData() {
            obs = new ArrayList<Observer>();//创建一个Observer集合
        }
    
        //天气信息设置
        public void setData(float temperature, float humidity, float pressure) {
            //为三个属性赋值
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
            changeWeather();//天气信息更改时调用方法
        }
    
        //天气信息更改时,更新观察者
        public void changeWeather() {
            notifyObservers();
        }
    
        @Override
        public void registerObserver(Observer ob) {
            if(!obs.contains(ob)) {
                obs.add(ob);
            }
        }
    
        @Override
        public void removeObserver(Observer ob) {
            if(obs.contains(ob)) {
                obs.remove(ob);
            }
        }
    
        @Override
        public void notifyObservers() {
            for(Observer ob : obs) {
                ob.update(temperature, humidity, pressure);
            }
        }
    
        //WeatherData的其他方法。。。
    }
    
    /*
     * 一个CurrentConditionsDisplay类实现Observer接口和DisplayElement接口:现实中可以有很多种CurrentConditionsDisplay类
     */
    public class CurrentConditionsDisplay implements Observer, DisplayElement {
    
        private float temperature;
        private float humidity;
        private float pressure;
        private Subject weatherData; 
    
        //无参构造方法
        public CurrentConditionsDisplay(){}
    
        //有参的构造方法:在创建CurrentConditionsDisplay的对象时,传入Subject接口实现类,调用实现类的registerObserver()方法,将观察者类注册进去
        public CurrentConditionsDisplay(Subject subject) {
            this.weatherData = subject;
            weatherData.registerObserver(this);
        }
    
        //注销观察者
        public void removeObserver() {
            weatherData.removeObserver(this);
        }
    
        @Override
        public void display() {
            System.out.println("今天的天气情况: 温度为" + temperature + "\t湿度为" + humidity + "\t气压为" + pressure);
        }
    
        @Override
        public void update(float temperature, float humidity, float pressure) {
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
            display();      
        }
    
    }
    

    Java内置的观察者模式

    让观察者类实现java.util包中的Observer接口,让可观察者继承java.util包中的Observable类
    修改过后的代码如下


    public class WeatherData extends Observable {
    
        //天气信息的三个属性
        private float temperature;//温度
        private float humidity;//湿度
        private float pressure;//气压
    
        //无参的构造方法
        public WeatherData() {}
    
        public void changeWeather() {
            setChanged();//标记状态已经改变的事实,只有调用此方法时,才会去更新观察者
            notifyObservers();
        }
    
        //天气信息设置
        public void setData(float temperature, float humidity, float pressure) {
            //为三个属性赋值
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
            changeWeather();//天气信息更改时调用方法
        }
    
        //生成get方法
        public float getTemperature() {
            return temperature;
        }
    
        public float getHumidity() {
            return humidity;
        }
    
        public float getPressure() {
            return pressure;
        }
    
    }
    
    /*
     * 一个DiaplayElement接口
     */
    public interface DisplayElement {
        //用于显示天气信息
        public void display();
    }
    
    public class CurrentConditionsDisplay implements DisplayElement, Observer {
    
        private Observable observable;
        //天气信息的三个属性
        private float temperature;//温度
        private float humidity;//湿度
        private float pressure;//气压
    
        //无参构造方法
        public CurrentConditionsDisplay() {}
    
        //有参构造方法
        public CurrentConditionsDisplay(Observable obs) {
            this.observable = obs;
            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();
                this.pressure = weatherData.getPressure();
                display();
            }
        }
    
        @Override
        public void display() {
            System.out.println("今天的天气情况: 温度为" + temperature + "\t湿度为" + humidity + "\t气压为" + pressure);
        }
    
    }
    

    注意:setChanged()方法。使用Java内置的观察者模式有个缺陷就是,可观察者是继承Observable类,如果可观察者已经继承其他父类,则无法实现观察者模式,由于Java中不支持多继承,因此,在使用该模式时,要视情况而定。

    相关文章

      网友评论

          本文标题:设计模式之观察者模式

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