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

Java 觀察者模式全解析:自訂實現與 JDK 內建 API 實戰對比

     編輯:Java 相關知識

觀察者模式核心定義

觀察者模式 定義物件間 一對多 依賴:當一個主題 狀態變更,所有依賴的觀察者自動收到通知並更新。典型應用:GUI 事件處理、訂閱發布系統、模型-視圖同步。

角色與協作

角色介面/類職責
Subject (主題)Observable 介面管理觀察者清單,提供註冊/移除/通知方法
ConcreteSubjectCup 類具體主題,狀態變更時呼叫 notifyObservers()
Observer (觀察者)Observer 介面定義 update() 方法,接收通知
ConcreteObserverPerson 類具體觀察者,實作 update() 回應變更

方案一:自訂介面實現 (純手工)

1. 定義主題介面

public interface Observable {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

2. 具體主題:價格變更觸發通知

public class Cup implements Observable {
    private List<Observer> observers = new ArrayList<>();
    private float price;

    public void setPrice(float price) {
        this.price = price;
        notifyObservers(); // 價格變更即通知
    }

    @Override
    public void notifyObservers() {
        for (Observer o : observers) {
            o.update(price); // 推模式:直接推送資料
        }
    }
    // register/remove 省略
}

3. 觀察者介面與實現

public interface Observer {
    void update(float price);
}

public class Person implements Observer {
    private String name;
    @Override
    public void update(float price) {
        System.out.println(name + " 收到通知:杯子價格更新為 " + price);
    }
}

4. 測試驗證

Cup cup = new Cup(3000);
cup.registerObserver(new Person("觀察者A"));
cup.registerObserver(new Person("觀察者B"));
cup.setPrice(2698); // 觸發兩個觀察者更新
cup.removeObserver(observerB); // 移除後不再收到
cup.setPrice(1998);

方案二:JDK 內建 API (java.util.Observable/Observer)

注意:JDK 9 標記 @Deprecated,建議改用 PropertyChangeListener、Flow API 或第三方庫 (RxJava, Reactor)。此處僅作教學示範。

1. 主題繼承 Observable

public class Cup extends Observable {
    private float price;
    public void setPrice(float price) {
        this.price = price;
        setChanged(); // 必須呼叫,標記狀態已變更
        notifyObservers(); // 呼叫無參版本,或 notifyObservers(arg) 傳遞資料
    }
}

2. 觀察者實作 Observer 介面

public class Person implements Observer {
    private String name;
    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof Cup) {
            System.out.println(name + " 收到通知:價格 " + ((Cup)o).getPrice());
        }
    }
}

3. 使用差異

  • 註冊:cup.addObserver(person) (非 register)
  • 移除:cup.deleteObserver(person)
  • 通知:setChanged() + notifyObservers() 兩步驟
  • update(Observable, Object) 簽名不同,需型別轉換取資料

兩種方案對比

維度自訂介面JDK Observable
靈活度高,完全控制介面設計低,綁定 JDK 固定簽名
推/拉模式任選 (範例為推模式)支援兩種,notifyObservers(arg) 為推
執行緒安全需自行實現內建同步 addObserver/notifyObservers
依賴零依賴依賴 JDK、已棄用
適用場景教學、輕量、特殊需求舊系統維護、簡單原型

觀察者模式核心價值

  1. 鬆耦合:主題僅知觀察者介面,不知具體類
  2. 支援廣播:一次狀態變更自動通知所有觀察者
  3. 層次分離:主題與觀察者可屬於不同抽象層級
  4. 動態關係:運行時可任意增減觀察者

現代替代方案建議

  • JavaBeans PropertyChangeListener:標準屬性變更通知
  • Spring ApplicationEvent:企業級事件總線
  • RxJava / Reactor (Reactive Streams):函式回應式、背壓、組合子豐富
  • Guava EventBus:輕量級進程內事件總線
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved