觀察者模式又稱發布-訂閱模式,定義物件間一對多依賴:當主題(Subject)狀態改變時,自動通知所有訂閱的觀察者(Observer)更新。核心價值在於解耦——主題與觀察者雙方都依賴抽象,而非具體實現。
| 角色 | 說明 | 核心方法 |
|---|---|---|
| Subject(抽象主題) | 管理觀察者列表,提供註冊/移除/通知 | attach, detach, notify |
| Observer(抽象觀察者) | 定義更新介面 | update() |
| ConcreteSubject | 具體主題,持有狀態 | getState, setState |
| ConcreteObserver | 具體觀察者,實作更新邏輯 | update() 內同步主題狀態 |

import java.util.ArrayList;
import java.util.List;
// 抽象主題
abstract class Subject {
private List<Observer> observers = new ArrayList<>();
public void attach(Observer ob) { observers.add(ob); }
public void detach(Observer ob) { observers.remove(ob); }
public void notifyObservers() {
for (Observer ob : observers) {
ob.update();
}
}
}
// 抽象觀察者
abstract class Observer {
public abstract void update();
}
// 具體觀察者
class ConcreteObserver extends Observer {
private String name;
private String observerState;
private ConcreteSubject subject;
public ConcreteObserver(ConcreteSubject subject, String name) {
this.subject = subject;
this.name = name;
}
@Override
public void update() {
observerState = subject.getSubjectState();
System.out.println(name + " 收到通知,狀態更新為:" + observerState);
}
}
// 具體主題
class ConcreteSubject extends Subject {
private String subjectState;
public String getSubjectState() { return subjectState; }
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
System.out.println("主題狀態變更為:" + subjectState);
}
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
subject.attach(new ConcreteObserver(subject, "觀察者X"));
subject.attach(new ConcreteObserver(subject, "觀察者Y"));
subject.attach(new ConcreteObserver(subject, "觀察者Z"));
subject.setSubjectState("Ready");
subject.notifyObservers();
}
}
主題狀態變更為:Ready
觀察者X 收到通知,狀態更新為:Ready
觀察者Y 收到通知,狀態更新為:Ready
觀察者Z 收到通知,狀態更新為:Ready
C++ 需手動管理記憶體:
detach,否則 Subject 仍持有野指標,下次 notify 導致 crashJava 9 起標記 @Deprecated,原因:
Observable 是類而非介面,限制繼承現代替代方案:
CopyOnWriteArrayList 保證線程安全| 優點 | 缺點 |
|---|---|
| 主題與觀察者鬆耦合 | 觀察者過多時通知延遲 |
| 支援廣播通訊 | 循環依賴導致死循環風險 |
| 符合開閉原則 | 若觀察者更新耗時,阻塞主題 |