觀察者模式定義對象間一對多依賴:當一個主題對象狀態變更,所有依賴它的觀察者自動收到通知並更新。典型場景:事件總線、GUI 監聽器、消息推送、緩存失效通知、數據同步觸發。
// 觀察者接口
public interface Observer {
void update(Object event); // 事件載體可為任意類型
}
// 被觀察者(主題)接口
public interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers(Object event);
}
public class ConcreteSubject implements Subject {
private final List<Observer> observers = new CopyOnWriteArrayList<>(); // 線程安全
@Override
public void attach(Observer observer) {
if (observer != null) observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers(Object event) {
for (Observer obs : observers) {
try {
obs.update(event);
} catch (Exception e) {
// 單個觀察者異常不影響其他
log.error("Observer update failed", e);
}
}
}
// 業務方法觸發通知
public void doBusinessLogic() {
// ... 業務處理 ...
notifyObservers(new BusinessEvent("ORDER_CREATED", orderId));
}
}
public class OrderNotificationObserver implements Observer {
@Override
public void update(Object event) {
if (event instanceof BusinessEvent) {
BusinessEvent be = (BusinessEvent) event;
if ("ORDER_CREATED".equals(be.getType())) {
// 發送郵件、推送、寫入消息隊列等
notificationService.sendOrderCreated(be.getOrderId());
}
}
}
}
public class ObserverPatternDemo {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer obs1 = new OrderNotificationObserver();
Observer obs2 = new InventoryUpdateObserver();
Observer obs3 = new LoggingObserver();
subject.attach(obs1);
subject.attach(obs2);
subject.attach(obs3);
subject.doBusinessLogic(); // 觸發三個觀察者更新
System.out.println("--- 移除 obs2 ---");
subject.detach(obs2);
subject.doBusinessLogic(); // 僅 obs1、obs3 響應
}
}
輸出:
OrderNotificationObserver 收到: ORDER_CREATED #1001
InventoryUpdateObserver 收到: ORDER_CREATED #1001
LoggingObserver 收到: ORDER_CREATED #1001
--- 移除 obs2 ---
OrderNotificationObserver 收到: ORDER_CREATED #1002
LoggingObserver 收到: ORDER_CREATED #1002
定義統一事件基類,攜帶類型、時間戳、來源、負載:
public class Event {
private final String type;
private final long timestamp = System.currentTimeMillis();
private final Object source;
private final Object payload;
// getter...
}
使用 ExecutorService 或 CompletableFuture 解耦通知耗時:
public void notifyObserversAsync(Event event) {
executor.submit(() -> notifyObservers(event));
}
觀察者若未顯式 detach,主題強引用導致無法 GC。改用 WeakReference<Observer> 存儲,通知時過濾失效引用。
生產環境推薦使用 ApplicationEventPublisher + @EventListener,框架級支持異步、排序、事務綁定。
java.util.Observable / Observer(Java 9 棄用,線程不安全、類而非接口)PropertyChangeSupport / PropertyChangeListener:JavaBeans 屬性變更通知標準EventListener 模式:Swing/AWT 事件模型基礎觀察者模式實現「鬆耦合通知」,核心在於主題不關心觀察者具體實現。手寫版適合輕量級場景,企業級開發優先使用 Spring Events、Guava EventBus、RxJava 等成熟框架,獲得異步、重試、死信隊列等企業級能力。