zoukankan      html  css  js  c++  java
  • 23种设计模式之观察者模式

    观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化

    1、Internet气象站项目

    提供温度、气压和湿度接口

    测量数据更新时需要通知给第三方

    需要设计开放型API,便于其他第三方公司也能接入气象站获取数据

    普通实现如下:

    2、WeatherData类

    测量数据更新时会调用类中的dataChange方法,dataChange方法中通过getTemperature、getPressure、getHumidity方法获得最新数据

     

    public class WeatherData {
    
        private float mTemperature;//温度
        private float mPreesure;//气压
        private float mHumidity;//湿度
    
        private CurrentConditions mCurrentConditions;
    
        public WeatherData(CurrentConditions currentConditions) {
            this.mCurrentConditions = currentConditions;
        }
    
        public float getTemperature() {
            return mTemperature;
        }
    
        public float getPreesure() {
            return mPreesure;
        }
    
        public float getHumidity() {
            return mHumidity;
        }
    
        //气象站数据变动后会调用该方法
        public void dataChange() {
            mCurrentConditions.update(getTemperature(), getPreesure(), getHumidity());
        }
    
        //模拟气象站数据变化,要调用dataChange方法
        public void setData(float mTemperature, float mPreesure, float mHumidity) {
            this.mTemperature = mTemperature;
            this.mPreesure = mPreesure;
            this.mHumidity = mHumidity;
            dataChange();
        }
    
    }
    WeatherData

     3、CurrentConditions类

    某公司想接入气象站,展示气象数据,气象数据更新时,会调用CurrentConditions类的update方法来更新展示的气象数据

    public class CurrentConditions {
    
        private float mTemperature;
        private float mPressure;
        private float mHumidity;
    
        public void update(float mTemperature, float mPressure, float mHumidity) {
            this.mTemperature = mTemperature;
            this.mPressure = mPressure;
            this.mHumidity = mHumidity;
            //假如更新后直接显示(也可以后期通过某条件后调用)
            display();
        }
    
        public void display() {
            System.out.println("***Today mTemperature: " + mTemperature + "***");
            System.out.println("***Today mPressure: " + mPressure + "***");
            System.out.println("***Today mHumidity: " + mHumidity + "***");
        }
    
    }
    CurrentConditions

    4、InternetWeather类

    气象站注册应用类,启动后,通过setData模拟气象数据变化

    public class InternetWeather {
    
        public static void main(String[] args) {
            CurrentConditions currentConditions;
            WeatherData weatherData;
    
            currentConditions = new CurrentConditions();
            weatherData = new WeatherData(currentConditions);
            weatherData.setData(30, 150, 40);
        }
    
    }
    InternetWeather

    5、引发的问题,如果再有其他公司想接入气象站,那么还要在WeatherData类中添加另一个公司的CurrentConditions类,同时还要停掉气象站服务,重新编译WeatherData类

    同样如果有公司不想接入气象站了,那么还要去除对应类对象,停服务重新编译

    6、使用观察者模式来解决此类问题,想接入气象站就去注册登记,不想接入就注册取消,登记的公司在气象数据变化后都会收到通知

    代码实现:

    public interface Subject {
    
        void registerObserver(Observer observer);
    
        void removeObserver(Observer observer);
    
        void notifyObservers();
    
    }
    Subject 接口
    public interface Observer {
    
        void update(float mTemperature,float mPressure,float mHumidity);
    
    }
    Observer 接口
    public class CurrentConditions implements Observer {
    
        private float mTemperature;
        private float mPressure;
        private float mHumidity;
    
        public void update(float mTemperature, float mPressure, float mHumidity) {
            this.mTemperature = mTemperature;
            this.mPressure = mPressure;
            this.mHumidity = mHumidity;
            display();
        }
    
        public void display(){
            System.out.println("***Today mTemperature: " + mTemperature + "***");
            System.out.println("***Today mPressure: " + mPressure + "***");
            System.out.println("***Today mHumidity: " + mHumidity + "***");
        }
    }
    CurrentConditions implements Observer
    public class ForcastConditions implements Observer {
    
        private float mTemperature;
        private float mPressure;
        private float mHumidity;
    
        public void update(float mTemperature, float mPressure, float mHumidity) {
            this.mTemperature = mTemperature;
            this.mPressure = mPressure;
            this.mHumidity = mHumidity;
            display();
        }
    
        public void display(){
            System.out.println("***Tomorrow mTemperature: " + mTemperature + "***");
            System.out.println("***Tomorrow mPressure: " + mPressure + "***");
            System.out.println("***Tomorrow mHumidity: " + mHumidity + "***");
        }
    }
    ForcastConditions implements Observer
    public class WeatherData implements Subject {
    
        private float mTemperature;//温度
        private float mPreesure;//气压
        private float mHumidity;//湿度
        private List<Observer> mObservers;
    
        public WeatherData() {
            mObservers = new ArrayList<Observer>();
        }
    
        public float getmTemperature() {
            return mTemperature;
        }
    
        public void setmTemperature(float mTemperature) {
            this.mTemperature = mTemperature;
        }
    
        public float getmPreesure() {
            return mPreesure;
        }
    
        public void setmPreesure(float mPreesure) {
            this.mPreesure = mPreesure;
        }
    
        public float getmHumidity() {
            return mHumidity;
        }
    
        public void setmHumidity(float mHumidity) {
            this.mHumidity = mHumidity;
        }
    
        //气象站数据变动后会调用该方法
        public void dataChange() {
            notifyObservers();
        }
    
        //模拟气象站数据变化,要调用dataChange方法
        public void setData(float mTemperature, float mPreesure, float mHumidity) {
            this.mTemperature = mTemperature;
            this.mPreesure = mPreesure;
            this.mHumidity = mHumidity;
            dataChange();
        }
    
        public void registerObserver(Observer observer) {
            mObservers.add(observer);
        }
    
        public void removeObserver(Observer observer) {
            if (mObservers.contains(observer))
                mObservers.remove(observer);
        }
    
        public void notifyObservers() {
            for (int i = 0; i < mObservers.size(); i++) {
                mObservers.get(i).update(getmTemperature(), getmPreesure(), getmHumidity());
            }
        }
    }
    WeatherData implements Subject
    public class InternetWeather {
    
        public static void main(String[] args) {
    
            CurrentConditions currentConditions;
            ForcastConditions forcastConditions;
            WeatherData weatherData;
    
            currentConditions = new CurrentConditions();
            forcastConditions = new ForcastConditions();
            weatherData = new WeatherData();
    
            weatherData.registerObserver(currentConditions);
            weatherData.registerObserver(forcastConditions);
    
            weatherData.setData(30, 150, 40);
            System.out.println("````````````````````");
            weatherData.removeObserver(forcastConditions);
            weatherData.setData(40,160,50);
    
    
        }
    
    }
    注册服务应用InternetWeather

    7、Java内置观察者(允许发出通知时直接推送给观察者,也可以通知观察者后让观察者来拉取数据)

    Java内置观察者使用的是Observable类(不是接口,作用类似实现Subject接口的类),和Observer接口

    注意,在观察者通知被观察者前要调用setChange方法

    public class CurrentConditions implements Observer {
    
        private float mTemperature;
        private float mPressure;
        private float mHumidity;
    
        public void update(Observable o, Object arg) {
            this.mTemperature=((Data)arg).mTemperature;
            this.mPressure=((Data)arg).mPressure;
            this.mHumidity=((Data)arg).mHumidity;
            display();
        }
    
        public void display(){
            System.out.println("***Today mTemperature: " + mTemperature + "***");
            System.out.println("***Today mPressure: " + mPressure + "***");
            System.out.println("***Today mHumidity: " + mHumidity + "***");
        }
    }
    Java内置观察者CurrentConditions implements Observer
    public class ForcastConditions implements Observer {
    
        private float mTemperature;
        private float mPressure;
        private float mHumidity;
    
        public void update(Observable o, Object arg) {
            this.mTemperature=((WeatherData.Data)arg).mTemperature;
            this.mPressure=((WeatherData.Data)arg).mPressure;
            this.mHumidity=((WeatherData.Data)arg).mHumidity;
            display();
        }
    
        public void display(){
            System.out.println("***Tomorrow mTemperature: " + mTemperature+1 + "***");
            System.out.println("***Tomorrow mPressure: " + mPressure+1 + "***");
            System.out.println("***Tomorrow mHumidity: " + mHumidity+1 + "***");
        }
    }
    Java内置观察者ForcastConditions implements Observer
    public class WeatherData extends Observable {
    
        private float mTemperature;//温度
        private float mPressure;//气压
        private float mHumidity;//湿度
    
        public float getmTemperature() {
            return mTemperature;
        }
    
        public void setmTemperature(float mTemperature) {
            this.mTemperature = mTemperature;
        }
    
        public float getmPreesure() {
            return mPressure;
        }
    
        public void setmPreesure(float mPreesure) {
            this.mPressure = mPreesure;
        }
    
        public float getmHumidity() {
            return mHumidity;
        }
    
        public void setmHumidity(float mHumidity) {
            this.mHumidity = mHumidity;
        }
    
        //气象站数据变动后会调用该方法
        public void dataChange() {
            this.setChanged();//一定要先调用这个方法,此方法是灵活设置是否通知观察者(如数据变化不大时不需要通知)
    //        this.notifyObservers();//通知观察者,来拉取数据
            this.notifyObservers(new Data(getmTemperature(),getmPreesure(),getmHumidity()));
        }
    
        //模拟气象站数据变化,要调用dataChange方法
        public void setData(float mTemperature, float mPressure, float mHumidity) {
            this.mTemperature = mTemperature;
            this.mPressure = mPressure;
            this.mHumidity = mHumidity;
            dataChange();
        }
    
        public class Data {
    
            public float mTemperature;//温度
            public float mPressure;//气压
            public float mHumidity;//湿度
    
            public Data(float mTemperature, float mPrsesure, float mHumidity) {
                this.mTemperature = mTemperature;
                this.mPressure = mPressure;
                this.mHumidity = mHumidity;
            }
        }
    }
    Java内置观察者WeatherData extends Observable
    public class InternetWeather {
    
        public static void main(String[] args) {
    
            CurrentConditions currentConditions;
            ForcastConditions forcastConditions;
            WeatherData weatherData;
    
            currentConditions = new CurrentConditions();
            forcastConditions = new ForcastConditions();
            weatherData = new WeatherData();
    
            //注意注册顺序,最后注册的先通知
            weatherData.addObserver(currentConditions);
            weatherData.addObserver(forcastConditions);
    
            weatherData.setData(30, 150, 40);
    
            System.out.println("````````````````````");
            weatherData.deleteObserver(forcastConditions);
            weatherData.setData(40,160,50);
    
    
        }
    
    }
    Java内置观察者WeatherData extends Observable
  • 相关阅读:
    asp.net六大对象
    python学习之类和实例的属性;装饰器@property
    第一次写博客,不知道写什么,就随便写一点咯
    Bash脚本编写初体验
    python学习之参数传递
    2016.9.30词法分析程序 108
    实验三 108
    10.28实验二 108
    词法分析实验报告 108
    组合数据类型练习,综合练习 108
  • 原文地址:https://www.cnblogs.com/hujiapeng/p/7899715.html
Copyright © 2011-2022 走看看