複製程式碼
import java.util.Vector;

//被觀察者類
public class Observable {
    //這是一個改變標識,來標記該被觀察者有沒有改變
    private boolean changed = false;
    //持有一個觀察者列表
    private Vector obs;
    
    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);
    }
    //notifyObservers(Object arg)的過載方法
    public void notifyObservers() {
    notifyObservers(null);
    }
    //通知所有觀察者,被觀察者改變了,你可以執行你的update方法了。
    public void notifyObservers(Object arg) {
        //一個臨時的陣列,用於併發訪問被觀察者時,留住觀察者列表的當前狀態,這種處理方式其實也算是一種設計模式,即備忘錄模式。
        Object[] arrLocal;
    //注意這個同步塊,它表示在獲取觀察者列表時,該物件是被鎖定的
    //也就是說,在我獲取到觀察者列表之前,不允許其他執行緒改變觀察者列表
    synchronized (this) {
        //如果沒變化直接返回
        if (!changed)
                return;
            //這裡將當前的觀察者列表放入臨時陣列
            arrLocal = obs.toArray();
            //將改變標識重新置回未改變
            clearChanged();
        }
        //注意這個for迴圈沒有在同步塊,此時已經釋放了被觀察者的鎖,其他執行緒可以改變觀察者列表
        //但是這並不影響我們當前進行的操作,因為我們已經將觀察者列表複製到臨時陣列
        //在通知時我們只通知陣列中的觀察者,當前刪除和新增觀察者,都不會影響我們通知的物件
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    //刪除所有觀察者
    public synchronized void deleteObservers() {
    obs.removeAllElements();
    }

    //標識被觀察者被改變過了
    protected synchronized void setChanged() {
    changed = true;
    }
    //標識被觀察者沒改變
    protected synchronized void clearChanged() {
    changed = false;
    }
    //返回被觀察者是否改變
    public synchronized boolean hasChanged() {
    return changed;
    }
    //返回觀察者數量
    public synchronized int countObservers() {
    return obs.size();
    }
}
複製程式碼