目錄
1、核心思想
2、實現方式
2.1 模式結構
2.2 實現案例
3、優缺點分析
4、適用場景
5、注意事項
1、核心思想
目的:針對被觀察對象與觀察者對象之間一對多的依賴關系建立起一種行為自動觸發機制,當被觀察對象狀態發生變化時主動對外發起廣播,以通知所有觀察者做出響應。核心目標是解耦主題與觀察者。
舉例:
1> Websocket協議:不需要像Http輪詢服務端的狀態,服務端可以主動推送消息給客戶端
2> 商店到貨,通知購買者列表中的人來購物
2、實現方式
2.1 模式結構
四個核心角色:
- Subject(目標主題)?:被觀察的目標主題的接口抽象,維護觀察者對象列表,并定義注冊方法register()(訂閱)與通知方法notify()(發布)?。
- ConcreteSubject(主題實現)?:被觀察的目標主題的具體實現類,持有一個屬性狀態State,維護觀察者列表,并在狀態變化時通知觀察者。
- Observer(觀察者)?:觀察者的接口抽象,定義響應方法update(),供主題調用。
- ConcreteObserver(觀察者實現)?:觀察者的具體實現類,可以有任意多個子類實現。實現了響應方法update(),收到通知后進行自己獨特的處理。
2.2 實現案例
當溫度變化時,通知手機和電視更改溫度顯示:
//1、主題接口:注冊、刪除、通知觀察者
public interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}//2、主題實現:溫度變化主題
public class WeatherStation implements Subject {private List<Observer> observers = new ArrayList<>();private float temperature;public void setTemperature(float temperature) {this.temperature = temperature;notifyObservers(); // 狀態變化時通知觀察者}@Overridepublic void registerObserver(Observer o) {observers.add(o);}@Overridepublic void removeObserver(Observer o) {observers.remove(o);}@Overridepublic void notifyObservers() {for (Observer o : observers) {o.update(temperature); // 推送數據給觀察者}}
}//3、觀察者接口
public interface Observer {void update(float temperature);
}//4、觀察者實現:手機、電視
public class PhoneDisplay implements Observer {@Overridepublic void update(float temperature) {System.out.println("手機顯示溫度更新:" + temperature + "℃");}
}public class TVDisplay implements Observer {@Overridepublic void update(float temperature) {System.out.println("電視顯示溫度更新:" + temperature + "℃");}
}//5、客戶端
public class Client {public static void main(String[] args) {WeatherStation station = new WeatherStation();PhoneDisplay phone = new PhoneDisplay();TVDisplay tv = new TVDisplay();// 注冊觀察者station.registerObserver(phone);station.registerObserver(tv);// 模擬溫度變化station.setTemperature(25.5f); // 輸出:// 手機顯示溫度更新:25.5℃// 電視顯示溫度更新:25.5℃// 移除一個觀察者station.removeObserver(tv);station.setTemperature(30.0f); // 輸出:手機顯示溫度更新:30.0℃}
}
兩種數據傳遞方式:
-
推模型(Push Model)
主題主動將數據推送給觀察者(如?
update(temperature)
)。 -
拉模型(Pull Model)
觀察者從主題拉取所需數據(如?
update()
?中調用?subject.getTemperature()
)。
3、優缺點分析
優點:
-
解耦:主題與觀察者無需知道彼此的具體實現。
-
動態訂閱:運行時動態添加或移除觀察者。
-
廣播通信:支持一對多通知,適合事件驅動系統。
-
遵循開閉原則:新增觀察者無需修改主題代碼。
缺點:
-
通知順序不可控:觀察者更新順序可能影響系統行為。
-
性能問題:大量觀察者或高頻更新可能導致性能瓶頸。
-
循環依賴風險:觀察者與主題間不當引用可能導致死循環。
4、適用場景
-
事件驅動系統
-
如GUI按鈕點擊事件、消息隊列通知。
-
-
實時數據同步
-
如股票價格變動通知、天氣數據更新。
-
-
跨模塊狀態同步
-
如電商系統中庫存變化觸發訂單狀態更新。
-
-
分布式系統
-
如微服務架構中的配置中心推送更新。
-
5、注意事項
-
避免內存泄漏
觀察者需及時取消注冊(如Android中Activity銷毀時移除監聽)。
-
線程安全
多線程環境下需同步觀察者列表(如使用?
CopyOnWriteArrayList
)。 -
防止過度通知
高頻更新場景可采用批量通知或節流機制(如每秒最多通知一次)。