生活随笔
收集整理的這篇文章主要介紹了
设计模式(二)————观察者模式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
引言
觀察者模式可以說是JDK中使用最多的模式之一,這個模式可以讓你的對象隨時隨地的了解想要知道的情況,你還可以讓某個對象在運行時決定是否要繼續通知;觀察者模式的定義為:
定義對象間一種一對多的依賴關系,使得當每一個對象改變狀態,則所有依賴于它的對象都會得到通知并自動更新
從定義就可以看出,觀察者模式主要就是兩部分:主題(Subject)和觀察者(Observer)
為了更清楚的了解觀察者模式,下面將會用案例說明觀察者模式;
天氣預報項目
今天一個新的項目交到了你的手上,這個項目是一個天氣預報公司的,他們想要
- 將每天測量到的溫度,濕度,氣壓等等以公告的形式發布出去
- 設計開放型 API,便于其他第三方也能接入氣象站獲取數據
- 而且天氣預報最基本的要求是準時,不能開始下雨了才把下雨的預報發出來,所以很重要的一點是:每當天氣預報更新的時候,要實時通知給第三方;
通過需求分析可以提煉出關鍵一點:公布天氣信息的“布告板”可以有多個,這些布告板全部從天氣預報公司獲取天氣信息;
大致是下圖的意思:
再加上實時更新的需求,就是對標觀察者模式;
上面圖可以等同于下面這個:
所以只需要確定好觀察者模式的兩個主要組成:主題(Subject)和觀察者(Observer)就好了;
很明顯,主題對象就是天氣預報公司,觀察者就是一系列第三方網站(的布告板);
接下來就是如何用方法將觀察者和主題聯系起來呢?
對于觀察者來說,需要的方法就是一個:
對于主題來說,需要以下功能:
- registerObserver() 注冊
- removeObserver() 移除
- notifyObservers() 通知注冊的用戶
那么就可以簡單嘗試畫出UML類圖了:
大致就是這樣,Subject是主題的接口,Observer是觀察者的接口,
可能你會覺得上面明明就說的那么簡單,怎么這一下子多了好幾個東西
其實這樣子的代碼耦合度更低,而且思路非常簡單,下面就來通過代碼實現一下就明白了;
主題:
public interface Subject {public void registerObserver(Observer o
); public void removeObserver(Observer o
); public void notifyObserver();
}
import java.util.ArrayList;public class WeatherData implements Subject {private ArrayList<Observer> observers
; private float temperature
; private float humidity
; private float pressure
; public WeatherData() {observers
= new ArrayList<>();}@Overridepublic void registerObserver(Observer o
) {observers
.add(o
);}@Overridepublic void removeObserver(Observer o
) {int i
= observers
.indexOf(o
);if (i
>= 0) {observers
.remove(o
);}}@Overridepublic void notifyObserver() {for (var i
: observers
) {i
.update(this.temperature
, this.humidity
, this.pressure
);}}public void measurementsChanged() {notifyObserver();}public void setMeasurements(float temperature
, float humidity
, float pressure
) {this.temperature
= temperature
;this.humidity
= humidity
;this.pressure
= pressure
;measurementsChanged(); }
}
觀察者:
public interface Observer {public void update(float temp
, float humidity
, float pressure
); public void display();
}
public class CurrentConditionsDisplay implements Observer{private float temperature
; private float humidity
; private float pressure
; @Overridepublic void update(float temp
, float humidity
, float pressure
) {this.temperature
= temp
;this.humidity
= humidity
;this.pressure
= pressure
;display();}@Overridepublic void display() {System.out
.println("當前溫度:" + this.temperature
+"當前濕度:" + this.humidity
+ "當前壓力:" + this.pressure
);}
}
public class BaiDuDisplay implements Observer{private float temperature
; private float humidity
; private float pressure
; @Overridepublic void update(float temp
, float humidity
, float pressure
) {this.temperature
= temp
;this.humidity
= humidity
;this.pressure
= pressure
;display();}@Overridepublic void display() {System.out
.println("百度溫度:" + this.temperature
+"百度濕度:" + this.humidity
+ "百度壓力:" + this.pressure
);}
}
還可以繼續增加布告板,這里就列舉這兩個了;
測試執行代碼:
public class WeatherStation {public static void main(String[] args
) {WeatherData weatherData
= new WeatherData();Observer current
= new CurrentConditionsDisplay(); Observer baidu
= new BaiDuDisplay(); weatherData
.registerObserver(current
); weatherData
.registerObserver(baidu
); weatherData
.setMeasurements(11, 22, 33);}
}
運行結果:
當前溫度:
11.0當前濕度:
22.0當前壓力:
33.0
百度溫度:
11.0百度濕度:
22.0百度壓力:
33.0
其實一看代碼,還是兩大部分,所以對于觀察者模式,主要思考的是主題和觀察者的關系就可以了;
使用了觀察者模式后,代碼有以下好處:
- 觀察者模式設計后,會以集合的方式來管理用戶(Observer),包括注冊,移除和通知
- 增加觀察者(即成一個新的公告板),就不需要去修改核心類 WeatherData 的代碼,遵守 ocp (開閉)原則
Java內置觀察者模式
JDK中提供了 java.util.Observable 實現類和 java.util.Observer 接口,這是Java內置的觀察者模式,可以直接來用,先簡單對比介紹一下:
- Observable 的作用和地位等價于前面的Subject
- Observable 是類,不是接口,類中已經實現了核心的方法 ,即管理 Observer 的方法 add… delete … notify…
- Observer 接口的作用等價于前面的 Observer接口, 都有update
- Observable類 和 Observer接口 的使用方法和前面講過的一樣,只是 Observable 是類,通過繼承來實現觀察者模式
下面我將用內置觀察者模式支持來重寫一下上面的代碼實現相同的功能;
主題:
import java.util.Observable;
public class WeatherData extends Observable {private float temperature
; private float humidity
; private float pressure
; public void measurementsChanged() {setChanged(); notifyObservers();}public void setMeasurements(float temperature
, float humidity
, float pressure
) {this.temperature
= temperature
;this.humidity
= humidity
;this.pressure
= pressure
;measurementsChanged();}public float getTemperature() {return temperature
;}public float getHumidity() {return humidity
;}public float getPressure() {return pressure
;}
}
觀察者:
import java.util.Observable;
import java.util.Observer;
public class CurrentConditionsDisplay implements Observer{private float temperature
; private float humidity
; private float pressure
; public void display() {System.out
.println("當前溫度為:" + this.temperature
+ " 當前濕度為:"+ this.humidity
+ " 當前壓力為:" + this.pressure
);}@Overridepublic void update(Observable o
, Object arg
) {if (o
instanceof WeatherData) {WeatherData weatherData
= (WeatherData) o
;this.temperature
= weatherData
.getTemperature();this.humidity
= weatherData
.getHumidity();this.pressure
= weatherData
.getPressure();display();}}
}
import java.util.Observable;
import java.util.Observer;
public class BaiDuDisplay implements Observer {private float temperature
; private float humidity
; private float pressure
; public void display() {System.out
.println("百度溫度為:" + this.temperature
+ " 百度濕度為:"+ this.humidity
+ " 百度壓力為:" + this.pressure
);}@Overridepublic void update(Observable o
, Object arg
) {if (o
instanceof WeatherData) {WeatherData weatherData
= (WeatherData) o
;this.temperature
= weatherData
.getTemperature();this.humidity
= weatherData
.getHumidity();this.pressure
= weatherData
.getPressure();display();}}
}
測試執行代碼:
public class WeatherStation {public static void main(String[] args
) {WeatherData weatherData
= new WeatherData(); CurrentConditionsDisplay currentConditionsDisplay
= new CurrentConditionsDisplay(); BaiDuDisplay baiDuDisplay
= new BaiDuDisplay(); weatherData
.addObserver(currentConditionsDisplay
); weatherData
.addObserver(baiDuDisplay
);weatherData
.setMeasurements(11, 22, 33);}
}
運行結果:
百度溫度為:
11.0 百度濕度為:
22.0 百度壓力為:
33.0
當前溫度為:
11.0 當前濕度為:
22.0 當前壓力為:
33.0
是不是有很多相同的地方,歸根結底都是使用的觀察者模式,所以只要知道觀察者模式由什么組成,什么時候用,那么你就真正了解了觀察者模式;
但是設計模式可不是隨便看看這倆代碼就能會用的,這也是設計模式不好學的一點,還是需要大量的代碼練習去體會,最后就能靈活運用;
注:在JDK中JavaBeans和Swing都實現了觀察者模式,感興趣可以嘗試一下;
總結
總結一下觀察者模式:
- 觀察者模式定義了對象之間一對多的關系
- 主題通過一個共同的接口來更新觀察者
- 觀察者和主題之間用松耦合的方式結合,主題不知道觀察者的細節,只知道觀察者實現了觀察者接口
- 當有多個觀察者時,不能依賴特定的通知次序
最后在這里展示一下觀察者模式的UML類圖:
在這篇文章中的例子的代碼只是為了展示觀察者模式,但是并不是最優的代碼,一個好的代碼可能要用到多種設計模式,這也是設計模式的一個難點;
設計模式的學習沒有什么技巧,只能在敲代碼的過程中不斷去體會,可能某一天你就會不自覺的使用設計模式,還是要多敲代碼多踩坑多思考,希望我們一起努力!!
歡迎大家的點評!
總結
以上是生活随笔為你收集整理的设计模式(二)————观察者模式的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。