美文网首页Java 杂谈
初步认识观察者模式

初步认识观察者模式

作者: AmeeLove | 来源:发表于2017-11-25 12:51 被阅读20次

    观察者模式又称为发布/订阅(Publish/Subscribe)模式,因此我们可以用报纸期刊的订阅来形象的说明:

    报社方负责出版报纸.

    你订阅了该报社的报纸,那么只要报社发布了新报纸,就会通知你,或发到你手上.

    如果你不想再读报纸,可以取消订阅,这样,报社发布了新报纸就不会再通知你.

    理解其实以上的概念,就可以理解观察者模式,观察者模式中有主题(Subject)和观察者(Observer),分别对应报社和订阅用户(你).观察者模式定义了对象之间的一对多的依赖关系,这样,当"一"的一方状态发生变化时,它所依赖的"多"的一方都会收到通知并且自动更新.如图:


    image.png image.png

    实现

    主题接口

    package com.ghgcn.model.observer1;
    
    public interface Obserable {
    
        /**
         * 注册
         * @param observer
         */
        public void registerObserver(Observer observer);
        
        /**
         * 取消订阅
         * @param observer
         */
        public void removeObserver(Observer observer);
        
        /**
         * 通知所有观察者
         */
        public void notifyObserver ();
        
    }
    
    

    观察者接口

    package com.ghgcn.model.observer1;
    
    /**
     * 观察都接口
     * @author Administrator
     *
     */
    public interface Observer {
    
        /**
         * 更新方法
         * @param temperature
         * @param humidity
         * @param pressure
         */
        void update(float temperature, float humidity, float pressure);
    
    }
    
    

    显示接口

    package com.ghgcn.model.observer1;
    
    public interface DispatyElement {
    
        public void display();
    }
    
    

    主题实现

    package com.ghgcn.model.observer1;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import com.sun.tracing.dtrace.ProviderAttributes;
    
    public class WeatherDate implements Obserable {
        
        /**
         * 用来存放观察者
         */
        private List<Observer> observers;
        
        private float temperature;
        private float humidity;
        private float pressure;
        
        public WeatherDate(){
            observers = new ArrayList<Observer>();
        }
    
        public void registerObserver(Observer observer) {
            observers.add(observer);
        }
    
        public void removeObserver(Observer observer) {
    
            int indexOf =observers.indexOf(observer);
            if(indexOf>=0){
                observers.remove(indexOf);
            }
        }
    
        public void notifyObserver() {
    
            for( int i = 0 ; i <observers.size() ; i++){
                Observer o=observers.get(i);
                o.update(this.temperature,this.humidity,this.pressure);
            }
        }
        
        
        /**
         * 改变,调用notifyObserver
         */
        public void measurementsChanged(){
            notifyObserver();
        }
        
        public void setMeasurements(float temperature,float humidity,    float pressure){
            this.temperature=temperature;
            this.humidity=humidity;
            this.pressure=pressure;
            measurementsChanged();
        }
    
        public List<Observer> getObservers() {
            return observers;
        }
    
        public void setObservers(List<Observer> observers) {
            this.observers = observers;
        }
    
        public float getTemperature() {
            return temperature;
        }
    
        public void setTemperature(float temperature) {
            this.temperature = temperature;
        }
    
        public float getHumidity() {
            return humidity;
        }
    
        public void setHumidity(float humidity) {
            this.humidity = humidity;
        }
    
        public float getPressure() {
            return pressure;
        }
    
        public void setPressure(float pressure) {
            this.pressure = pressure;
        }
    
    }
    
    

    观察者实现

    package com.ghgcn.model.observer1;
    
    public class CurrentConditionsDisplay implements Observer, DispatyElement {
    
        private Obserable weatherDate;
        
        private float temperature;
        private float humidity;
        private float pressure;
        
        
        public CurrentConditionsDisplay(Obserable weatherDate){
            this.weatherDate=weatherDate;
            weatherDate.registerObserver(this);
        }
        
        public void display() {
            
            System.out.println("CurrentConditionsDisplay :\n temperature: "+this.temperature+" \n  humidity:"+this.humidity+"\n pressure:"+this.pressure);
        }
    
        public void update(float temperature, float humidity, float pressure) {
            this.temperature=temperature;
            this.humidity=humidity;
            this.pressure=pressure;
            display();
        }
    
        
    
    }
    
    

    测试

    package com.ghgcn.model.observer1;
    
    public class Test1 {
    
        public static void main(String[] args) {
            
            WeatherDate weatherDate = new WeatherDate();
            
            
            CurrentConditionsDisplay c1 = new CurrentConditionsDisplay(weatherDate);
            //CurrentConditionsDisplay c2 = new CurrentConditionsDisplay(weatherDate);
            //CurrentConditionsDisplay c3 = new CurrentConditionsDisplay(weatherDate);
    
            weatherDate.setMeasurements(32.6f, 65.3f, 30.4f);
            weatherDate.setMeasurements(20.6f, 33.1f, 67.8f);
            weatherDate.setMeasurements(18.6f, 45.2f, 88.9f);
            weatherDate.setMeasurements(-20.6f, 35.6f, 93.0f);
        }
    
    }
    
    

    结果

    CurrentConditionsDisplay :
     temperature: 32.6 
      humidity:65.3
     pressure:30.4
    CurrentConditionsDisplay :
     temperature: 20.6 
      humidity:33.1
     pressure:67.8
    CurrentConditionsDisplay :
     temperature: 18.6 
      humidity:45.2
     pressure:88.9
    CurrentConditionsDisplay :
     temperature: -20.6 
      humidity:35.6
     pressure:93.0
    
    

    JAVA内置的观察者

    主题 是一个类不是一个接口

    public class Observable {
    //标题位, 为true中通知观察都
        private boolean changed = false;
    //存放所有的订阅者
        private Vector<Observer> obs;
    
        /** Construct an Observable with zero Observers. */
    
        public Observable() {
    //构造方法初始化容器
            obs = new Vector<>();
        }
    
        /**
        添加观察者,也就是注册 这里加了同步锁
         */
        public synchronized void addObserver(Observer o) {
            if (o == null)
                throw new NullPointerException();
            if (!obs.contains(o)) {
                obs.addElement(o);
            }
        }
    
        /**
      移除观察者
         */
        public synchronized void deleteObserver(Observer o) {
            obs.removeElement(o);
        }
    
        /**
       通知所有观察者发生变化了
         */
        public void notifyObservers() {
            notifyObservers(null);
        }
    
        /**
       通知所有观察者发生变化了 
         */
        public void notifyObservers(Object arg) {
            /*
    缓冲容器
             */
            Object[] arrLocal;
    
            synchronized (this) {
                /* 
    判断标题位是否为true,false就不向下执行通知,为 true时才通知
                 */
                if (!changed)
                    return;
        //初始化缓冲容器,所有操作都在这个容器上实现
                arrLocal = obs.toArray();
    //清除标识位,设置为false
                clearChanged();
            }
    
      //发送通知
            for (int i = arrLocal.length-1; i>=0; i--)
                ((Observer)arrLocal[i]).update(this, arg);
        }
    
        /**
         * 删除订阅者
         */
        public synchronized void deleteObservers() {
            obs.removeAllElements();
        }
    
        /**
      一定要调用这个方法,设置标识位为true,再调用notifyObservers才可以发送通知
         */
        protected synchronized void setChanged() {
            changed = true;
        }
    
        /**
      清楚标识位,设置为false
         */
        protected synchronized void clearChanged() {
            changed = false;
        }
    
        /**
      获取标识位
         */
        public synchronized boolean hasChanged() {
            return changed;
        }
    
        /**
      获取订阅者数量
         */
        public synchronized int countObservers() {
            return obs.size();
        }
    }
    
    

    观察者

    public interface Observer {
        /**
      就一个方法更新在 上面notifyObservers 方法中有调用
         */
        void update(Observable o, Object arg);
    }
    
    

    JAVA内置观察者实现

    主题

    package com.ghgcn.model.javaobserver2;
    
    import java.util.Observable;
    
    /**
     * JAVA内置的主题
     * 
     * @author Administrator
     *
     */
    public class SubjectDate extends Observable {
        private float temperature;
        private float humidity;
        private float pressure;
    
        
        public SubjectDate() {
            super();
        }
        
        public SubjectDate(float temperature, float humidity, float pressure) {
            super();
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
        }
    
        public float getTemperature() {
            return temperature;
        }
    
        public void setTemperature(float temperature) {
            this.temperature = temperature;
        }
    
        public float getHumidity() {
            return humidity;
        }
    
        public void setHumidity(float humidity) {
            this.humidity = humidity;
        }
    
        public float getPressure() {
            return pressure;
        }
    
        public void setPressure(float pressure) {
            this.pressure = pressure;
        }
    
        
        public void measurementsChanged(){
            /**
             *  发生改变
                    
             */
            setChanged(); //changed=true
            /**
             * 通知
             */
            notifyObservers();
        }
    
    }
    
    

    观察者

    package com.ghgcn.model.javaobserver2;
    
    import java.util.Observable;
    import java.util.Observer;
    
    import com.ghgcn.model.observer1.DispatyElement;
    import com.ghgcn.model.observer1.WeatherDate;
    
    public class CurrentDisplay implements DispatyElement, Observer {
    
        private Observable subjectDate;
    
        private float temperature;
        private float humidity;
        private float pressure;
    
        public CurrentDisplay(Observable subjectDate) {
            this.subjectDate = subjectDate;
            subjectDate.addObserver(this);
        }
    
        public void update(Observable o, Object arg) {
            if (o instanceof SubjectDate) {
                SubjectDate sub = (SubjectDate)o;
                this.temperature=sub.getTemperature();
                this.humidity=sub.getHumidity();
                this.pressure=sub.getHumidity();
                display();
            }
        }
    
        public void display() {
            System.out.println("CurrentConditionsDisplay :\n temperature: " + this.temperature + " \n  humidity:"
                    + this.humidity + "\n pressure:" + this.pressure);
        }
    
        public float getTemperature() {
            return temperature;
        }
    
        public void setTemperature(float temperature) {
            this.temperature = temperature;
        }
    
        public float getHumidity() {
            return humidity;
        }
    
        public void setHumidity(float humidity) {
            this.humidity = humidity;
        }
    
        public float getPressure() {
            return pressure;
        }
    
        public void setPressure(float pressure) {
            this.pressure = pressure;
        }
    
    }
    
    
    package com.ghgcn.model.javaobserver2;
    
    import java.util.Observable;
    import java.util.Observer;
    
    import com.ghgcn.model.observer1.DispatyElement;
    import com.ghgcn.model.observer1.WeatherDate;
    
    public class CurrentDisplay2 implements DispatyElement, Observer {
    
        private Observable subjectDate;
    
        private float temperature;
        private float humidity;
        private float pressure;
    
        public CurrentDisplay2(Observable subjectDate) {
            this.subjectDate = subjectDate;
            subjectDate.addObserver(this);
        }
    
        public void update(Observable o, Object arg) {
            if (o instanceof SubjectDate) {
                SubjectDate sub = (SubjectDate)o;
                this.temperature=sub.getTemperature();
                this.humidity=sub.getHumidity();
                this.pressure=sub.getHumidity();
                display();
            }
        }
    
        public void display() {
            System.out.println("CurrentDisplay2 :\n temperature: " + this.temperature + " \n  humidity:"
                    + this.humidity + "\n pressure:" + this.pressure);
        }
    
        public float getTemperature() {
            return temperature;
        }
    
        public void setTemperature(float temperature) {
            this.temperature = temperature;
        }
    
        public float getHumidity() {
            return humidity;
        }
    
        public void setHumidity(float humidity) {
            this.humidity = humidity;
        }
    
        public float getPressure() {
            return pressure;
        }
    
        public void setPressure(float pressure) {
            this.pressure = pressure;
        }
    
    }
    
    
    

    显示

    package com.ghgcn.model.javaobserver2;
    
    public interface DisplayElement {
    
        public void display();
    }
    
    
    
    

    测试

    package com.ghgcn.model.javaobserver2;
    
    public class Test1 {
    
        public static void main(String[] args) {
            SubjectDate subjectDate = new SubjectDate(32.6f, 65.3f, 30.4f);
            
            CurrentDisplay c1 = new CurrentDisplay(subjectDate);
            
            CurrentDisplay2 c2 = new CurrentDisplay2(subjectDate);
    
            subjectDate.measurementsChanged();
        }
    
    }
    
    

    结果

    CurrentDisplay2 :
     temperature: 32.6 
      humidity:65.3
     pressure:65.3
    CurrentConditionsDisplay :
     temperature: 32.6 
      humidity:65.3
     pressure:65.3
    
    

    并没有按订阅的顺序执行

    相关文章

      网友评论

        本文标题:初步认识观察者模式

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