java源碼閱讀Observable(觀察者模式)

1類簽名和簡介java

package java.util;
public class Observable

Observable是Java內置的觀察者模式中的主題類(沒錯,是類不是接口),和其對應的觀察者接口是Observer,觀察者模式是JDK中使用最多的模式之一。數組

觀察者模式定義了對象之間的一對多的關係,這樣一來,當一個對象(主題)改變狀態時,它的全部依賴者(觀察者)都會收到通知並自動更新。安全

Observable內部使用Vector來存儲註冊的觀察者實例,是線程安全的。app

注意:jdk將Observable實現爲類而不是接口,那麼就限制了其使用和複用性,由於Java是單繼承的。ide

 

2成員屬性測試

private boolean changed = false;
private Vector<Observer> obs;

當changed屬性爲true時才更行觀察者們,該類實現了其set和清除change狀態的方法。this

obs存儲觀察者。spa

protected synchronized void setChanged() {
        changed = true;
    }

protected synchronized void clearChanged() {
        changed = false;
    }

public synchronized boolean hasChanged() {
        return changed;
    }

 

3成員方法線程

(1)註冊code

public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

將觀察者註冊到主題。

(2)註銷

 public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

將觀察者從主題中註銷

(3)通知

public void notifyObservers() {
        notifyObservers(null);
    }

public void notifyObservers(Object arg) {
        //臨時數組,存儲vector中全部的觀察者
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }
        //遍歷全部觀察者並調用其update方法
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

 

4使用Observable實現觀察者模式

場景:氣象站每次更新氣溫,都到通知給3個不一樣的app廠商。

氣象站表示主題,用WeatherData類表示。

3個App廠商表示觀察者,用App一、App二、App3類表示。

import java.util.Observable;

public class WeatherData extends Observable {

    private float temperature;
    
    public void tempChanged(){
        setChanged();
        notifyObservers();
    }

    public float getTemperature() {
        return temperature;
    }

    public void setTemperature(float temperature) {
        this.temperature = temperature;
        tempChanged();
    }
    
    
}

主題每次set溫度的時候,都會通知全部的觀察者,會調用觀察者的update進行更新。觀察者App1的代碼以下(App2和App3同樣)

import java.util.Observable;
import java.util.Observer;

public class App1 implements Observer {
    
    Observable observable;
    private float temperature;
    
    public App1(Observable observable){
        this.observable = observable;
        this.observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        // TODO Auto-generated method stub

        if(o instanceof WeatherData){
            WeatherData wd = (WeatherData)o;
            this.temperature = wd.getTemperature();
            display();
        }
    }
    
    public void display(){
        System.out.println("當前溫度:"+this.temperature+"攝氏度");
    }

}

實例化App1的時候會註冊到主題,下面是場景測試。

public class Test {

    public static void main(String[] args) {

        //實例化主題
        WeatherData wd = new WeatherData();
        //實例化觀察者,並傳入主題
        App1 app1 = new App1(wd);
        //每次改變溫度時,都會通知觀察者更新輸出。
        wd.setTemperature(20);
        wd.setTemperature(22);
        
    }     
}

運行結果以下:

當前溫度:20.0攝氏度
當前溫度:22.0攝氏度

完!

相關文章
相關標籤/搜索