項目介紹:高溫預警系統旨在氣象部門根據氣象衛星獲得相關的天氣溫度信息,當溫度超過某一閾值時,向各個單位和個人發出高溫警報通知,以及時做好高溫防護措施。這是一個典型的觀察者模式使用場景。
項目代碼鏈接:
https://github.com/hj841104031/MyJavaProject
系統結構圖如下圖所示:

模式分析:
高溫預警過程分析
1.想要得到溫度信息,這需要氣溫關注者 “訂閱”高溫預警服務。
Observer的接口定義如下:
package Observer;
public interface Observer {
public void update(Subject subject);
}
Person類對Observer的具體實現如下:
package Observer;
public class Person implements Observer {
public Person(Subject subject) {
subject.add(this);
}
public void update(Subject subject) {
System.out.println("個人收到高溫預警:" + subject.temperatureReport());
}
}
觀察者接口定義了update的方法,當有溫度信息時接收溫度信息。程序代碼中包含有三個觀察者,分別是Person、Company與Government。這三個具體的觀察者分別對update函數進行了相應的重寫。
總的來說觀察者模式在被觀察者和觀察者之間建立一個抽象的耦合。被觀察者角色所知道的只是一個具體現察者聚集,每一個具體觀察者都符合一個抽象觀察者的接口。被觀察者並不認識任何一個具體觀察者,它只知道它們都有一個共同的接口。
2.高溫預警系統需要知道哪些對象是需要通知的。這需要預警系統維護一個關注者列表。
3.高溫預警系統在溫度達到閾值的時候,通知所有“訂閱”服務的關注者。如何通知呢?這需要氣溫關注者具備接收通知的功能。
為了實現以上兩個功能需要將Subject接口的定義如下:
package Observer;
public interface Subject {
// 增加觀察者
public boolean add(Observer observer);
// 刪除觀察者
public boolean remove(Observer observer);
// 通知所有觀察者更新數據
public void notifyAllObserver();
// 設置溫度值
public void setTemperature(float temperature);
// 獲得溫度預警
public String temperatureReport();
}
這個抽象主題類實現了以下的功能:
- 增加觀察者
- 刪除觀察者
- 通知所有觀察者更新數據
- 設置溫度值
- 獲得溫度預警
以及對Subject接口的具體實現類ForcastSystem的代碼如下:
package Observer;
import java.util.Iterator;
import java.util.Vector;
public class ForcastSystem implements Subject {
private float temperature; // 溫度
private String warningLevel; // 預警級別
private final Vector<Observer> vector; // 觀察者列表
// 構造方法 初始化觀察者列表
public ForcastSystem() {
vector = new Vector<Observer>();
}
// 增加觀察者
public boolean add(Observer observer) {
if (observer != null && !vector.contains(observer)) {
return vector.add(observer);
}
return false;
}
// 移除觀察者
public boolean remove(Observer observer) {
return vector.remove(observer);
}
// 通知所有觀察者更新數據
public void notifyAllObserver() {
System.out.println("======氣象部門發布高溫" + this.warningLevel + "警報!======");
Iterator<Observer> iterator = vector.iterator();
while (iterator.hasNext()) {
(iterator.next()).update(this);
}
}
// 私有方法 根據溫度值設置預警級別 然后通知所有觀察者
private void invoke() {
if (this.temperature >= 35) {
if (this.temperature >= 35 && this.temperature < 37) {
this.warningLevel = "黃色";
} else if (this.temperature >= 37 && this.temperature < 40) {
this.warningLevel = "橙色";
} else if (this.temperature >= 40) {
this.warningLevel = "紅色";
}
// 通知所有觀察者溫度狀況
this.notifyAllObserver();
}
}
// 設置溫度值
public void setTemperature(float temperature) {
this.temperature = temperature;
this.invoke();
}
// 獲得溫度預警
public String temperatureReport() {
return " 溫度:" + this.temperature;
}
public void notifyAllObserver()這個函數調用了iterator迭代器來判斷是否有數據信息的更新操作,如果有新的數據被更新,則向所有的觀察者發送最新的溫度消息。
總的來看 高溫預警系統和氣溫關注者,兩者關系如下圖所式:

靜態建模
進一步將整個系統抽象,形成的靜態關系結構如下圖所示。

觀察者模式的優點
- 當一個抽象模型有兩個方面,其中一個方面依賴於另一個方面。在我們的這個網絡監控中,觀察者依賴於被觀察者。
- 當對一個對象的改變需要同時改變其它對象,而不知道具體有多少個對象待改變。當被觀察者的數據要發生改變時,對應的觀察者的數據也要改變,這個時候只要將被觀察者里的觀察者集合都改變了就可以了
- 當一個對象必須通知其它對象,而它又不能假定其它對象是誰。換句話說,你不希望這些對象是緊密耦合的。
- 在觀察者和被觀察者之間建立了一個耦合,對於被觀察者來說,他只對它的觀察者集合負責,然后具體的網絡改變都是通過接口傳遞,只需要改變setTempearture()與notifyAllObserver()即可,剩下的不需要被觀察者在意。被觀察者也不需要知道觀察者都有些誰。
- 而對於觀察者而言,它不需要知道被觀察者的情況,只需要知道接口傳下來的netaciton(具體動作如網絡狀態、WiFi改變),執行自己的update()更新自己的狀態即可。
- 它們沒有緊密的耦合,可以屬於不同的抽象化層次
- 一旦數據改變,支持廣播通信很適合被觀察者向每一個觀察者廣播改變網絡狀態的通知。
