觀察者模式定義對象間一對多依賴:主題狀態變更時,自動通知所有觀察者。廣泛應用於事件總線、GUI 監聽、消息推送、Spring ApplicationEvent 等場景。
| 角色 | 職責 | 典型實現 |
|---|---|---|
| 抽象主題 | 管理觀察者集合,提供註冊/移除/通知接口 | 接口 Watched |
| 抽象觀察者 | 定義更新接口 | 接口 Watcher |
| 具體主題 | 狀態變更時調用通知,攜帶業務數據 | 類 ConcreteWatched |
| 具體觀察者 | 實現更新邏輯,同步主題狀態 | 類 ConcreteWatcher |
public interface Watcher {
void update(String event); // 也可傳遞 EventObject 豐富載荷
}
public interface Watched {
void addWatcher(Watcher watcher);
void removeWatcher(Watcher watcher);
void notifyWatchers(String event);
}
public class ConcreteWatcher implements Watcher {
@Override
public void update(String event) {
System.out.println("收到通知: " + event);
// 實際業務:刷新 UI、發送郵件、寫日誌...
}
}
import java.util.*;
public class ConcreteWatched implements Watched {
private final List<Watcher> watchers = new ArrayList<>();
@Override
public void addWatcher(Watcher watcher) {
if (!watchers.contains(watcher)) watchers.add(watcher);
}
@Override
public void removeWatcher(Watcher watcher) {
watchers.remove(watcher);
}
@Override
public void notifyWatchers(String event) {
// 建議複製列表防止並發修改,或用 CopyOnWriteArrayList
for (Watcher w : new ArrayList<>(watchers)) {
w.update(event);
}
}
// 業務方法觸發通知
public void doBusiness() {
// ... 業務邏輯
notifyWatchers("高興");
}
}
public class ObserverDemo {
public static void main(String[] args) {
Watched subject = new ConcreteWatched();
subject.addWatcher(new ConcreteWatcher());
subject.addWatcher(new ConcreteWatcher());
subject.addWatcher(new ConcreteWatcher());
subject.notifyWatchers("高興"); // 或 subject.doBusiness();
}
}
CopyOnWriteArrayList 或鎖保護。notifyWatchers 提交到線程池,避免阻塞主題線程。String 升級為 EventObject 子類,攜帶源、時間戳、負載。WeakReference<Watcher> 防止觀察者無法 GC(如 GUI 組件)。ApplicationEventPublisher + @EventListener 實現解耦的域事件總線。java.util.Observable / Observer(Java 9 棄用,不推薦新代碼使用)。PropertyChangeSupport / PropertyChangeListener(JavaBeans 屬性變更通知)。觀察者模式核心在於主題不依賴具體觀察者,通過接口解耦。手寫版本適合輕量級場景;企業級應用建議直接使用 Spring 事件機制或成熟事件總線。掌握手寫實現,能深度理解框架底層原理。