一、什么是觀察者模式?
觀察者模式(Observer Pattern)是一種行為型設計模式,用于對象之間的一對多依賴關系:當被觀察對象(Subject)狀態發生變化時,所有依賴它的觀察者(Observer)都會自動收到通知并更新。
拿天氣預報系統來類比
假設你是一個氣象局的中央發布系統,每當你更新天氣預報,訂閱了你天氣服務的各種渠道(如手機 App、LED 公交站牌、廣播系統)都會自動收到通知并顯示新的天氣情況。
- 氣象局 = 被觀察者(Subject)
- 各種顯示設備 = 觀察者(Observer)
- 通知機制 = 觀察者模式的核心精髓
二、模式結構圖
三、代碼實戰
我們構建一個完整的天氣通知系統:
WeatherStation
是被觀察者PhoneDisplay
和LedBoardDisplay
是觀察者
1. Observer 接口
public interface Observer {void update(float temperature, float humidity, float pressure);
}
2. Subject 接口
public interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}
3. WeatherStation(被觀察者)
import java.util.ArrayList;
import java.util.List;public class WeatherStation implements Subject {private List<Observer> observers = new ArrayList<>();private float temperature, humidity, pressure;@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, humidity, pressure);}}public void setMeasurements(float temp, float hum, float press) {this.temperature = temp;this.humidity = hum;this.pressure = press;notifyObservers(); // 狀態變了,通知大家!}
}
4. 兩個觀察者實現類
手機顯示端
public class PhoneDisplay implements Observer {@Overridepublic void update(float temperature, float humidity, float pressure) {System.out.println("[手機App] 當前天氣:溫度=" + temperature + "℃,濕度=" + humidity + "%,氣壓=" + pressure + " hPa");}
}
LED 公交站牌
public class LedBoardDisplay implements Observer {@Overridepublic void update(float temperature, float humidity, float pressure) {System.out.println("[LED站牌] 實時天氣:T=" + temperature + "℃ | H=" + humidity + "% | P=" + pressure + " hPa");}
}
5. 主程序測試
public class WeatherApp {public static void main(String[] args) {WeatherStation station = new WeatherStation();Observer phone = new PhoneDisplay();Observer led = new LedBoardDisplay();station.registerObserver(phone);station.registerObserver(led);station.setMeasurements(28.5f, 60f, 1012f);station.setMeasurements(30.1f, 55f, 1008f);}
}
四、實戰示例UML 圖
@startuml
interface Observer {+update(temp, humidity, pressure)
}interface Subject {+registerObserver(o: Observer)+removeObserver(o: Observer)+notifyObservers()
}class WeatherStation implements Subject {-observers: List<Observer>-temperature: float-humidity: float-pressure: float+setMeasurements(temp, hum, press)
}class PhoneDisplay implements Observer
class LedBoardDisplay implements ObserverSubject <|.. WeatherStation
Observer <|.. PhoneDisplay
Observer <|.. LedBoardDisplay
WeatherStation --> Observer : notifies >>
@enduml
五、優點與應用場景
優點
- 低耦合性:Subject 和 Observer 相互獨立,只通過接口聯系;
- 靈活可擴展:任意添加/刪除觀察者,不影響其他模塊;
- 符合開閉原則:修改 Subject 不影響 Observer 行為。
典型應用場景
- GUI 事件系統(按鈕點擊監聽)
- 消息訂閱與發布(如 Kafka、MQTT)
- 數據驅動的響應式 UI 框架(React/Vue 背后的思想)
- 游戲狀態監聽器(如玩家血量變化通知 UI)
六、小結
一句話總結觀察者模式: “我變了,我的訂閱者們會立刻知道。”
觀察者模式本質上是發布-訂閱模式的一種實現。通過本篇“天氣預報”類比,我們不僅理解了模式的結構,還體驗了它在實際開發中的強大威力。
七、參考
《23種設計模式概覽》