設計模式真香筆記-觀察者模式
阿新 • • 發佈:2018-11-09
觀察者模式的介紹
觀察者模式:物件之間一對多依賴,當一個物件改變狀態的時候,它的所有依賴都會收到通知並且自動更新。
這樣說可能有些人不能理解,我們來舉個生動形象的例子:
許多人以前會經常訂閱雜誌,雜誌社會定期發雜誌給訂閱者,當然他也可以取消訂閱,那麼雜誌社就不會繼續發雜誌給訂閱者。
這個例子裡面雜誌社就是可觀察者,而訂閱者就相當於觀察者,雜誌社定期更新會通知他的所有依賴也就是訂閱者。
再來個圖促進理解:
利用到的新原則
- 為互動物件之間的鬆耦合設計而努力
觀察者模式的例子(氣象臺佈告板例子)
UML類圖
有空在畫圖。
實現程式碼附帶一些解釋
- Subject介面
/**
* Subject介面為可觀察者(主題)介面
* @
*/
public interface Subject {
/**
* @param o 傳入引數為觀察者介面實現物件
*/
void registerObserver(Observer o);//註冊為觀察者
void removeObserver(Observer o);//退出觀察者
void notifyObserevers();//當主題資料改變時及時候通知觀察者。
}
- Observer介面
public interface Observer {//觀察者介面
void update(float temperature, float humidity,float pressure);//更新資料
}
- display介面
public interface Display {//顯示資料
void display();
}
- WeatherData(實現可觀察介面成為可觀察者)
public class WeatherData implements Subject {
private ArrayList observers;
private float temperature;//溫度
private float humidity;//溼度
private float pressure;//氣壓
public WeatherData(){
observers = new ArrayList();//用於觀察者註冊的集合
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if(i>=0){
observers.remove(i);
}
}
@Override
public void notifyObserevers() {
for (Object observer: observers
) {
Observer observer1 = (Observer) observer;
observer1.update(temperature,humidity,pressure);
}
}
public void measurementsChanged(){//更新通知
notifyObserevers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {//改變觀察者資料
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
measurementsChanged();
}
//其他擴充套件方法
}
- CurrentConditionDisplay (實現觀察者介面成為觀察者)
public class CurrentConditionDisplay implements Observer,Display {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionDisplay(Subject weatherData){//構造方法實現註冊為觀察者
this.weatherData=weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {//顯示資料
System.out.println("CurrentConditionDisplay:"+temperature+"Humidity"+humidity);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature=temperature;
this.humidity=humidity;
display();
}
}
- CurrentConditionDisplayM(實現觀察者介面成為觀察者)
public class CurrentConditionDisplayM implements Observer,Display {
private float temperature;
private float humidity;
private float pressure;
private Subject weatherData;
public CurrentConditionDisplayM(Subject weatherData){
this.weatherData=weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("CurrentConditionDisplayM:"+temperature*3+"Humidity"+humidity/2+"pressure"+pressure*4);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
display();
}
}
- WeatherStation(氣象站類也就是測試類)
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);
CurrentConditionDisplayM currentConditionDisplayM = new CurrentConditionDisplayM(weatherData);
weatherData.setMeasurements(80,68,29.2f);
weatherData.setMeasurements(90,100,23);
}
}
- 列印結果
觀察者模式的總結
可觀察者和觀察者之間用鬆耦合的形式結合,可觀察者只知道觀察者實現了觀察者的介面,而不知道觀察者具體內容。
有多個觀察者時候,不可以依賴特定的通知次序。
swing類庫中就有很多使用觀察者模式的例子,譬如說:點選按鈕新增多種監聽器,實現不同的功能。
一些補充
在java.util 類庫中有實現好的觀察者模式。Observable.java(可觀察者類是類不是介面),在這類裡面有一個setchanged()方法用來標記可觀察者的狀態的事實,那他的意義是什麼呢?我們不需要標記就可以更新啊,其實他的作用是為了控制可觀察者的更新頻率,我們可以通過這個方法實現上面的氣象站例子 三天,或者半個月更新一次,沒有這個方法,我們沒有辦法控制,氣象站就會實時更新。具體我們可以java.util類庫中Observable.java的原始碼。
本文參考:《Head First 設計模式》