首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 觀察者模式深度解析:從內建 API 到自定義事件過濾

     編輯:Java 程式設計入門

核心概念:觀察者模式

觀察者模式定義了一種一對多的依賴關係:當一個主題對象的狀態發生變化時,所有依賴它的觀察者都會收到通知並自動更新。這實現了主題與觀察者之間的鬆散耦合。

四大核心角色

  • 抽象主題:管理觀察者集合,提供註冊/移除介面。
  • 具體主題:儲存狀態,狀態改變時通知所有觀察者。
  • 抽象觀察者:定義更新介面 update()。
  • 具體觀察者:實現更新介面,保持與主題狀態同步。

實戰一:Java 內建 Observer API 模擬按鈕事件

Java 在 java.util 包下提供了 Observable 類與 Observer 介面,可直接用於快速構建觀察者機制。

關鍵點:必須先呼叫 setChanged()

Observable 內部有一個 changed 標誌(預設 false)。notifyObservers() 會先檢查此標誌,唯有 true 時才會分發通知。因此流程必須是:

  1. 狀態改變
  2. setChanged()
  3. notifyObservers(args)

程式碼結構

// 1. 被觀察者:繼承 Observable
public class MyButton extends Observable {
    public void addListeners(Observer o) { addObserver(o); }
    public void process(Object args) {
        setChanged();          // 關鍵步驟
        notifyObservers(args); // 分發通知
    }
}

// 2. 觀察者:實現 Observer 介面
public class ClickObserver implements Observer {
    public void update(Observable o, Object arg) {
        System.out.println("click: " + arg);
    }
}

// 3. 測試驅動
MyButton btn = new MyButton();
btn.addObserver(new ClickObserver());
btn.process("huhx"); // 輸出: click: huhx

原理深度剖析:Observable 內部運作

  • 使用 Vector 儲存觀察者(線程安全)。
  • addObserver() 同步加入向量。
  • notifyObservers() 同步複製觀察者陣列,清除 changed 標誌,然後反向遍歷呼叫 update()。

進階實戰:自定義 Observer 實現事件類型過濾

內建 API 無法針對特定事件類型通知特定觀察者。自定義框架可解決此問題。

架構設計

  1. 事件常量類:定義 CLICK、PRESS、ALL 等事件類型。
  2. Listener 介面:取代 Observer,方法簽名為 actionPerformed(MyObservable, Object)。
  3. 具體監聽器:ClickListener、PressListener 等。
  4. MyObservable:核心分發引擎,根據事件類型在 notifyFixObserver 中進行 instanceof 判斷並精準分發。
  5. AbstractButton / MyButton:封裝通用邏輯,簡化使用。

核心分發邏輯片段

private void notifyFixObserver(int event, Object args) {
    for (int i = arrLocal.length - 1; i >= 0; i--) {
        Listener listener = (Listener) arrLocal[i];
        switch (event) {
            case Event.CLICK:
                if (listener instanceof ClickListener) 
                    ((ClickListener)listener).actionPerformed(this, args);
                break;
            case Event.PRESS:
                if (listener instanceof PressListener) 
                    ((PressListener)listener).actionPerformed(this, args);
                break;
            case Event.ALL:
                listener.actionPerformed(this, args);
                break;
        }
    }
}

總結與最佳實踐

方案優點缺點適用場景
java.util.Observer零依賴、標準化需繼承類、無事件過濾、已棄用 (Java 9+)簡單、單一事件類型的通知
自定義 Listener支援事件過濾、介面導向、無繼承限制需自行維護框架代碼複雜業務、多事件類型、需解耦

現代開發中,推薦使用 ApplicationEventPublisher (Spring) 或 EventBus (Guava/GreenRobot) 等成熟事件總線框架,它們提供了異步、註解驅動、線程池隔離等企業級特性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved