核心特點
- 觀察者模式 經典實作:事件源 + 事件物件 + 監聽器介面。
- 介面導向:監聽器為單一方法介面 (SAM),Java 8+ 可用 Lambda 簡寫。
- 非侵入式:事件源不依賴具體監聽器實作,僅依賴介面。
- 多播:一個事件源可註冊多個監聽器。
標準結構
// 1. 事件物件 (承載上下文)
class MyEvent extends EventObject {
private String message;
public MyEvent(Object source, String msg) { super(source); this.message = msg; }
public String getMessage() { return message; }
}
// 2. 監聽器介面 (擴充 EventListener 標記介面)
interface MyListener extends EventListener {
void onEvent(MyEvent e); // 單一方法
}
// 3. 事件源 (維護監聽器列表、觸發)
class EventSource {
private final List listeners = new CopyOnWriteArrayList<>(); // 執行緒安全
public void addListener(MyListener l) { listeners.add(l); }
public void removeListener(MyListener l) { listeners.remove(l); }
protected void fireEvent(String msg) {
MyEvent event = new MyEvent(this, msg);
for (MyListener l : listeners) l.onEvent(event);
}
}
反例:非所有監聽器都叫 onClick / 僅用於按鈕
| 監聽器 | 事件來源 | 方法名 | 應用場景 |
| ActionListener | Button, MenuItem, Timer | actionPerformed | 動作觸發 |
| MouseListener | Component | mouseClicked/Pressed/Released... | 滑鼠互動 |
| KeyListener | Component | keyPressed/Released/Typed | 鍵盤輸入 |
| PropertyChangeListener | JavaBean | propertyChange | 屬性變更綁定 |
| HttpSessionListener | Servlet Container | sessionCreated/Destroyed | Session 生命週期 |
| TimerTask / ScheduledExecutor | 排程器 | run() | 定時任務 (非 GUI) |
Java 8+ Lambda 簡寫
button.addActionListener(e -> System.out.println("Clicked: " + e.getActionCommand()));
// 替代匿名內部類 new ActionListener() { ... }
自訂監聽器最佳實踐
- 介面命名:`Listener` (如 `PaymentListener`)。
- 方法命名:`on` (如 `onPaymentSuccess`)。
- 事件物件攜帶不可變資料,避免監聽器修改源狀態。
- 使用
CopyOnWriteArrayList 或 EventListenerList (Swing) 管理列表,保證執行緒安全與移除時不影響疊代。