美文网首页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

并没有按订阅的顺序执行

相关文章

  • 初步认识观察者模式

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

  • 无标题文章

    初步学习RxJava 基本概念 Observable:发射源,英文释义“可观察的”,在观察者模式中称为“被观察者”...

  • 观察者设计模式

    前言 相信大家搞开发的,肯定对观察者模式会经常听说,本文就带着大家认识一下较为神秘的观察者模式吧. 观察者模式,顾...

  • 观察者模式

    What 观察者模式 我们可以先通过生活上的事情来认识观察者模式,在日常生活中订阅报纸就可以看成是观察者模式的实现...

  • 观察者模式

    1.认识观察者模式 通过报纸的订阅来认识观察者模式:①报社的业务就是出版报纸②向某家报社订阅报纸,只要他们有新报纸...

  • 11.9设计模式-观察者模式-详解

    设计模式-观察者模式 观察者模式详解 观察者模式在android中的实际运用 1.观察者模式详解 2.观察者模式在...

  • RxJava基础—观察者模式

    设计模式-观察者模式 观察者模式:观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式...

  • MVC模式的初步认识

    MVC是什么? MVC是model-view-controller的英文简称,中文的意思是模型-视图-控制器。MV...

  • 前端面试考点之手写系列

    1、观察者模式 观察者模式(基于发布订阅模式) 有观察者,也有被观察者。 观察者需要放到被观察者列表中,被观察者的...

  • 01.观察者模式

    01.观察者模式 1、认识观察者模式: 我们看看报纸和杂志的订阅是怎么回事: (1)报社的业务就是出版报纸。 (2...

网友评论

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

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