本文參考Head First設計模式一書,感受書中的例子實在很好,很貼切。對模式的知識點進行總結,並對書的源碼作了必定註釋。
觀察者模式要點有二:主題和觀察者。
最貼切的案例是:雜誌訂閱,雜誌是主題,觀察者是訂閱者。當出版新雜誌時候,這個事件會自動通知全部的訂閱者。
根據OO基本原則,應該針對接口編程(固然緣由不少),主題和訂閱者通常都做爲接口。
下面是Head First的例子,是一個氣象站,用戶訂閱氣象信息的服務。
而且,最終用戶所要的信息多是:
針對這個需求,應用觀察者模式來實現:
可是這個只是一個主題與觀察者的設計,觀察者自身還須要將信息顯示出去。那麼再用一個接口,專門來實現展現的功能。
實際上,上面的DisplayElement接口用再此處,本質上是策略模式的應用。
理解每一個模式的特色對交流和設計都有很大幫助,當OO思想境修煉到很高的程度時,應該是忘掉全部的模式,而能夠根據須要作出最佳設計,這個程度能夠算手中無劍,心中有劍的地步。
下面是源碼,只列出接口:
/**
* 主題
*/
public
interface Subject {
public
void registerObserver(Observer o);
public
void removeObserver(Observer o);
public
void notifyObservers();
}
/**
* 觀察者
*/
public
interface Observer {
public
void update(
float temp,
float humidity,
float pressure);
}
/**
* 佈告板
*/
public
interface DisplayElement {
public
void display();
}
測試main方法:
public
static
void main(String[] args) {
//建立主題
WeatherData weatherData =
new WeatherData();
//建立三個觀察者
CurrentConditionsDisplay currentDisplay =
new CurrentConditionsDisplay(weatherData);
StatisticsDisplay statisticsDisplay =
new StatisticsDisplay(weatherData);
ForecastDisplay forecastDisplay =
new ForecastDisplay(weatherData);
HeatIndexDisplay heatIndexDisplay =
new HeatIndexDisplay(weatherData);
//進行氣象測量,主題的狀態會由於測量值而改變
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
本例僅僅是爲了說明這種模式,設計還遠不夠完美。實際上,主題中應該有一個線程去掃描狀態的變化,當變化了,自動去調用measurementsChanged()方法。
觀察者模式使用很廣泛,GUI編程中事件註冊就是典型的觀察者模式的應用。
以上是本身實現的觀察者模式,下文將講述JDK所實現的觀察者模式。