Java觀察者模式定義物件間一對多的依賴關係,當一個物件(被觀察者)的狀態發生改變時,所有依賴於它的物件(觀察者)都得到通知並自動更新。JDK中提供的觀察者模式的實現是由java.util.Observer介面和java.util.Observable類組成的,其中Observer代表觀察者,而Observable代表被觀察者。
工具/原料
java.util.Observer
java.util.Observable
方法/步驟
Observable類是由被觀察者(可有一個或多個觀察者)所繼承,呼叫setChanged方法,是的hasChanged方法返回值為true,則再次呼叫notifyObservers方法會觸發觀察者的update方法來通知觀察者該例項發生變化。
Observer介面中只有一個為實現的update抽象方法,實現該介面的物件稱為觀察者,該物件要實現update方法。註冊了該物件(觀察者)的物件(被觀察者)例項在呼叫notifyObservers方法之後,會自動呼叫觀察者中的update方法。
被觀察者I114gBoxHeaterObservable.java,代表熱水器,繼承Obserable,其實現如下:
package com.i114gbox.sdk.designMode.observer;
import java.util.Observable;
/**
* 熱水器--被觀察者
*
* @author [email protected]
*
*/
public class I114gBoxHeaterObservable extends Observable {
// 水溫
private int temperature;
public int getTemperature() {
return temperature;
}
public void setTemperature(int temperature) {
this.temperature = temperature;
}
// 燒水
public void boilWater() {
for (int i = 10; i <= 100;) {// 初始水溫為15度
temperature = i;
// 呼叫setChanged(),hasChanged()將返回true
this.setChanged();
// 當hasChanged()返回true時,監聽被觀察者的觀察者將呼叫update()
this.notifyObservers();
i += 10;
}
}
}
在扮演觀察者角色的同時,又扮演被觀察者的角色,類名為I114gBoxDisplayObservable.java,代表顯示器,繼承Observable類,實現Observer介面,其實現如下:
package com.i114gbox.sdk.designMode.observer;
import java.util.Observable;
import java.util.Observer;
import java.util.logging.Logger;
/**
* 顯示器--觀察者(用於觀察熱水器),被觀察者(被報警器觀察)
*
* @author [email protected]
*
*/
public class I114gBoxDisplayObservable extends Observable implements Observer {
private static Logger logger = Logger
.getLogger(I114gBoxDisplayObservable.class.getSimpleName());
private String status = I114gBoxWaterStatus.COLD.toString();
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
// 顯示水溫
private void displayTemperature(int temperature) {
// 當水被燒開時
if (temperature == 100) {
this.setStatus(I114gBoxWaterStatus.HOT.toString());
this.setChanged();
this.notifyObservers(temperature);
}
logger.info("水狀態為:" + status + " " + "現在水溫為:" + temperature);
}
// 當被觀察者狀態發生改變時,呼叫該方法
@Override
public void update(Observable observable, Object data) {
this.displayTemperature(((I114gBoxHeaterObservable) observable)
.getTemperature());
}
}
觀察者I114gBoxAlarmObserver.java,代表報警器,實現Observer介面,其實現如下:
package com.i114gbox.sdk.designMode.observer;
import java.util.Observable;
import java.util.Observer;
import java.util.logging.Logger;
/**
* 報警器--觀察者
*
* @author [email protected]
*
*/
public class I114gBoxAlarmObserver implements Observer {
private static Logger logger = Logger.getLogger(I114gBoxAlarmObserver.class
.getSimpleName());
// 當水燒開了呼叫該方法
@Override
public void update(Observable observable, Object data) {
this.makeAlarm((Integer) data);
}
// 報警
private void makeAlarm(int temperature) {
logger.info("滴滴滴……水燒開了!");
}
}
觀察者模式測試類Test.java,其實現如下:
package com.i114gbox.sdk.designMode.observer;
/**
* 觀察者模式測試類
*
* @author [email protected]
*
*/
public class Test {
public static void main(String[] args) {
I114gBoxHeaterObservable heater = new I114gBoxHeaterObservable();
I114gBoxDisplayObservable display = new I114gBoxDisplayObservable();
I114gBoxAlarmObserver alarm = new I114gBoxAlarmObserver();
// 加入觀察者
// 顯示器用來觀察熱水器
heater.addObserver(display);
// 報警器用來觀察顯示器
display.addObserver(alarm);
// 燒水
heater.boilWater();
}
}
執行測試類,結果如下:
注意事項
優點:支援鬆耦合和減少依賴性;觀察者數目可變
缺點:效能降低;記憶體洩露;測試除錯困難