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


1類簽名和簡介

package java.util;
public class Observable

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

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

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

注意:jdk將Observable實現為類而不是接口,那么就限制了其使用和復用性,因為Java是單繼承的。

 

2成員屬性

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

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

obs存儲觀察者。

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

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

public synchronized boolean hasChanged() {
        return changed;
    }

 

3成員方法

(1)注冊

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廠商表示觀察者,用App1、App2、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攝氏度

完!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM