觀察者模式(發佈-訂閱模式)

觀察者模式簡介:

定義:定義對象間的一對多的依賴關係,當一個對象的狀態改變時,所有依賴於它的對象都得到通知並被自動更新。

 

使用例子:

網上商店中的商品在名稱、價格發生變化時,必須自動通知會員,Java的API爲我們提供了Observer接口和Observable類來實現觀察者模式。
  Observable(可觀察者)類允許在自身發生改變時,通知其它對象(實現接口Observer,觀察者)。

 

使用java.util.Observer接口和java.util.Observable類實現觀察者模式:

觀察者實現Observer接口,並重寫其中的update方法,供被觀察者狀態改變時調用。

被觀察者繼承Observable類,在Observable類中有增加,刪除觀察者類的方法,還有通知所有觀察者都update的方法。狀態改變時,先setChanged,再notifyObservers。

 

Observer觀察者接口源碼:

 

package java.util;    
public interface Observer    
{    
/**   
* 當被觀察的對象發生變化時,這個方法會被調用。   
*/    
void update(Observable o, Object arg);    
}   

 

 

被觀察者Observable類源碼:

package java.util;    
public class Observable    
{    
private boolean changed = false;    
private Vector obs;    
/** 用0個觀察者構造一個被觀察者。**/    
public Observable()    
{    
obs = new Vector();    
}    
/**   
* 將一個觀察者加到觀察者列表上面。   
*/    
public synchronized void addObserver(Observer o)    
{    
if (!obs.contains(o))    
{    
obs.addElement(o);    
}    
}    
/**   
* 將一個觀察者對象從觀察者列表上刪除。   
*/    
public synchronized void deleteObserver(Observer o)    
{    
obs.removeElement(o);    
}    
/**   
* 相當於 notifyObservers(null)   
*/    
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;    
}    
/**   
* 返還被觀察對象(即此對象)的觀察者總數。   
*/    
public synchronized int countObservers()    
{    
return obs.size();    
}    
} 

 

 

下面是一個被觀察者(產品類):

 

import java.util.*;
public class product extends Observable{ 
   private String name;////產品名
   private float price;////價格

   public String getName(){ return name;}
   public void setName(String name){
    this.name=name;
   ////設置變化點 
    setChanged();
    notifyObservers(name);////通知觀察者

   }   

   public float getPrice(){ return price;}
   public void setPrice(float price){
    this.price=price;
   ////設置變化點
    setChanged();
    notifyObservers(new Float(price)); 

   }

   ////以下可以是數據庫更新 插入命令.
   public void saveToDb(){
   System.out.println("saveToDb");
    }

}

 

 

下面是兩個觀察者:

import java.util.*;
public class NameObserver implements Observer{

   private String name=null;
   public void update(Observable obj,Object arg){
     if (arg instanceof String){
      name=(String)arg;
      ////產品名稱改變值在name中
      System.out.println("NameObserver :name changet to "+name);

     }

      }
   }

import java.util.*;
public class PriceObserver implements Observer{
   private float price=0;
   public void update(Observable obj,Object arg){
     if (arg instanceof Float){

      price=((Float)arg).floatValue();
  
      System.out.println("PriceObserver :price changet to "+price);

     }


   }

}

 

 

下面是測試類:

public class Test {

   public static void main(String args[]){
    Product product=new Product();
    Observer nameobs=new NameObserver();
    Observer priceobs=new PriceObserver();

    ////加入觀察者
    product.addObserver(nameobs);
    product.addObserver(priceobs);

    product.setName("applet");
    product.setPrice(9.22f); 

   }
}

 

 

 

運行結果:
C:\java>java  Test
NameObserver :name changet to applet
PriceObserver :price changet to 9.22

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