觀察者模式(發布-訂閱)是 GUI、事件總線、反應式編程的基石。本文基於 Java 8 Stream API 與 Lambda,從經典 GoF 結構演進至專業化簡化版,深入剖析執行緒安全、有序通知、Mixin 復用、適配器模式、複雜/阻塞監聽器處理等實戰難題,附完整可運行代碼。
| 經典 GoF | 專業化簡化版 |
|---|---|
| Subject/Observer 介面雙向依賴 | 單向:Subject 持有 Listener 列表,Listener 只需實作單一方法 |
| Observer 拉取狀態 | Subject 推送狀態物件給 Listener(參數化通知) |
| attach/detach 命名 | registerXXXListener / unregisterXXXListener |
class Animal { private String name; /* getter/setter/建構子 */ }
@FunctionalInterface // 單一方法,支援 Lambda
interface AnimalAddedListener { void onAnimalAdded(Animal animal); }
class Zoo {
private final List<Animal> animals = new ArrayList<>();
private final List<AnimalAddedListener> listeners = new ArrayList<>();
public void addAnimal(Animal a) {
animals.add(a);
notifyAnimalAddedListeners(a);
}
public AnimalAddedListener registerAnimalAddedListener(AnimalAddedListener l) {
listeners.add(l); return l; // 回傳引用便於解除註冊
}
public void unregisterAnimalAddedListener(AnimalAddedListener l) {
listeners.remove(l);
}
protected void notifyAnimalAddedListeners(Animal a) {
listeners.forEach(l -> l.onAnimalAdded(a)); // Java 8 forEach + Lambda
}
}
Zoo zoo = new Zoo();
// Lambda 註冊
AnimalAddedListener listener = zoo.registerAnimalAddedListener(
a -> System.out.println("新增動物:" + a.getName()));
zoo.addAnimal(new Animal("老虎")); // 輸出:新增動物:老虎
zoo.unregisterAnimalAddedListener(listener);
zoo.addAnimal(new Animal("獅子")); // 無輸出
ReentrantReadWriteLock:寫鎖保護註冊/解除,讀鎖保護通知遍歷。new ReentrantReadWriteLock(true) 保證 FIFO 順序,避免飢餓。abstract class ObservableSubjectMixin<L> {
private final List<L> listeners = new ArrayList<>();
public L registerListener(L l) { listeners.add(l); return l; }
public void unregisterListener(L l) { listeners.remove(l); }
public void notifyListeners(Consumer<? super L> action) {
listeners.forEach(action);
}
}
class ZooUsingMixin extends ObservableSubjectMixin<AnimalAddedListener> {
private final List<Animal> animals = new ArrayList<>();
public void addAnimal(Animal a) {
animals.add(a);
notifyListeners(l -> l.onAnimalAdded(a));
}
}
interface ZooListener {
default void onAnimalAdded(Animal a) {}
default void onAnimalRemoved(Animal a) {}
}
class ZooAdapter implements ZooListener {} // 空實作
class NamePrinter extends ZooAdapter {
@Override public void onAnimalAdded(Animal a) {
System.out.println("新增:" + a.getName());
}
}
ExecutorService,實現生產者-消費者模式。shutdown())。監聽器介面:XxxListener / XxxEventListener
註冊方法:registerXxxListener(listener) → 回傳 listener
解除方法:unregisterXxxListener(listener)
通知方法:notifyXxxListeners(event) // 複數 s 表示批量
事件物件:XxxEvent (單一狀態物件)
掌握這套模式,無論是 Swing 事件、Spring ApplicationEvent、RxJava、Kotlin Flow 皆可融會貫通。