觀察者模式 定義物件間 一對多 依賴:當一個主題 狀態變更,所有依賴的觀察者自動收到通知並更新。典型應用:GUI 事件處理、訂閱發布系統、模型-視圖同步。
| 角色 | 介面/類 | 職責 |
|---|---|---|
| Subject (主題) | Observable 介面 | 管理觀察者清單,提供註冊/移除/通知方法 |
| ConcreteSubject | Cup 類 | 具體主題,狀態變更時呼叫 notifyObservers() |
| Observer (觀察者) | Observer 介面 | 定義 update() 方法,接收通知 |
| ConcreteObserver | Person 類 | 具體觀察者,實作 update() 回應變更 |
public interface Observable {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
public class Cup implements Observable {
private List<Observer> observers = new ArrayList<>();
private float price;
public void setPrice(float price) {
this.price = price;
notifyObservers(); // 價格變更即通知
}
@Override
public void notifyObservers() {
for (Observer o : observers) {
o.update(price); // 推模式:直接推送資料
}
}
// register/remove 省略
}
public interface Observer {
void update(float price);
}
public class Person implements Observer {
private String name;
@Override
public void update(float price) {
System.out.println(name + " 收到通知:杯子價格更新為 " + price);
}
}
Cup cup = new Cup(3000);
cup.registerObserver(new Person("觀察者A"));
cup.registerObserver(new Person("觀察者B"));
cup.setPrice(2698); // 觸發兩個觀察者更新
cup.removeObserver(observerB); // 移除後不再收到
cup.setPrice(1998);
注意:JDK 9 標記 @Deprecated,建議改用 PropertyChangeListener、Flow API 或第三方庫 (RxJava, Reactor)。此處僅作教學示範。
public class Cup extends Observable {
private float price;
public void setPrice(float price) {
this.price = price;
setChanged(); // 必須呼叫,標記狀態已變更
notifyObservers(); // 呼叫無參版本,或 notifyObservers(arg) 傳遞資料
}
}
public class Person implements Observer {
private String name;
@Override
public void update(Observable o, Object arg) {
if (o instanceof Cup) {
System.out.println(name + " 收到通知:價格 " + ((Cup)o).getPrice());
}
}
}
cup.addObserver(person) (非 register)cup.deleteObserver(person)setChanged() + notifyObservers() 兩步驟update(Observable, Object) 簽名不同,需型別轉換取資料| 維度 | 自訂介面 | JDK Observable |
|---|---|---|
| 靈活度 | 高,完全控制介面設計 | 低,綁定 JDK 固定簽名 |
| 推/拉模式 | 任選 (範例為推模式) | 支援兩種,notifyObservers(arg) 為推 |
| 執行緒安全 | 需自行實現 | 內建同步 addObserver/notifyObservers |
| 依賴 | 零依賴 | 依賴 JDK、已棄用 |
| 適用場景 | 教學、輕量、特殊需求 | 舊系統維護、簡單原型 |