一個簡易的java自帶的觀察者模式實現

      觀察者模式是對象的行爲模式,又叫發佈-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式。

      觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。

JAVA提供的對觀察者模式的支持

    在JAVA語言的java.util庫裏面,提供了一個Observable類以及一個Observer接口,構成JAVA語言對觀察者模式的支持。
      

Observer接口

    這個接口只定義了一個方法,即update()方法,當被觀察者對象的狀態發生變化時,被觀察者對象的notifyObservers()方法就會調用這一方法。
    
public interface Observer {

    void update(Observable o, Object arg);
}
       

Observable類

     被觀察者類都是java.util.Observable類的子類。java.util.Observable提供公開的方法支持觀察者對象,這些方法中有兩個對Observable的子類非常重要:一個是setChanged(),另一個是notifyObservers()。第一方法setChanged()被調用之後會設置一個內部標記變量,代表被觀察者對象的狀態發生了變化。第二個是notifyObservers(),這個方法被調用時,會調用所有登記過的觀察者對象的update()方法,使這些觀察者對象可以更新自己。
    
public class Observable {
    private boolean changed = false;
    private Vector 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);
    }

    /**
     * 如果本對象有變化(那時hasChanged 方法會返回true)
     * 調用本方法通知所有登記的觀察者,即調用它們的update()方法
     * 傳入this和arg作爲參數
     */
    public void notifyObservers(Object arg) {

        Object[] arrLocal;

    synchronized (this) {

        if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    /**
     * 將觀察者聚集清空
     */
    public synchronized void deleteObservers() {
    obs.removeAllElements();
    }

    /**
     * 將“已變化”設置爲true
     */
    protected synchronized void setChanged() {
    changed = true;
    }

    /**
     * 將“已變化”重置爲false
     */
    protected synchronized void clearChanged() {
    changed = false;
    }

    /**
     * 檢測本對象是否已變化
     */
    public synchronized boolean hasChanged() {
    return changed;
    }

    /**
     * Returns the number of observers of this <tt>Observable</tt> object.
     *
     * @return  the number of observers of this object.
     */
    public synchronized int countObservers() {
    return obs.size();
    }
}
         這個類代表一個被觀察者對象,有時稱之爲主題對象。一個被觀察者對象可以有數個觀察者對象,每個觀察者對象都是實現Observer接口的對象。在被觀察者發生變化時,會調用Observable的notifyObservers()方法,此方法調用所有的具體觀察者的update()方法,從而使所有的觀察者都被通知更新自己。
         下面是我寫的一個簡單的觀察者模式的實現,這裏用milk表示牛奶訂購者,模擬觀察者對象Observer,用milkShop表示牛奶店,模擬被觀察者對象(主題對象),模擬邏輯是牛奶訂購者向牛奶店訂購牛奶,當牛奶店有新的牛奶到貨就通知訂購者。
      
public class Milk implements Observer{
	public String Num;
	/*
	 * update是Observer的實現方法arg1是subject傳回的結果數據,這裏可以主動獲取,也可以獲取數據爲標誌,然後再拉取
	   (non-Javadoc)
	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
	 */
    public void update(Observable arg0, Object arg1) {
		// TODO Auto-generated method stub
		
		Num=(String )arg1;
		System.out.println("********************"+Num);
	}

}
  被觀察者的代碼如下
public class MilkShop extends Observable{
	
	public String Num;

	public String getNum() {
		return Num;
	}

	public void setNum(String num) {
		Num = num;
		DateChange();
	}
	/*
	 * 數據變化,通知註冊在他這裏的觀察者,並且把數據傳給觀察者
	 */

	 
    public void  DateChange(){
    	
    	this.setChanged();
    	this.notifyObservers(Num);
    	
    }	

}
      測試類的代碼如下
public class TestObserver {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
              Milk mMilk=new Milk();
              MilkShop mMilkShop=new MilkShop();
              /*
              * subject添加觀察者,
              */
              mMilkShop.addObserver(mMilk);
              /*
               * 模擬subject數據變化,然後通知觀察者數據變化,並且將數據傳給觀察者
               */
             mMilkShop.setNum("27");
	}

}
   然後輸出結果如下:





     
    


      

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章