觀察者模式簡介:
定義:定義對象間的一對多的依賴關係,當一個對象的狀態改變時,所有依賴於它的對象都得到通知並被自動更新。
使用例子:
網上商店中的商品在名稱、價格發生變化時,必須自動通知會員,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