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

Java 觀察者模式實戰:基於 JDK 內建 Observable 與 Observer 完整指南

     編輯:Java 相關知識

觀察者模式定義對象間的一對多依賴,當主題狀態改變時,自動通知所有觀察者。Java 在 java.util 包中提供了 Observable 類與 Observer 接口,開箱即用,無需第三方庫。本文通過兩個完整案例演示其核心用法與進階技巧。

核心機制速覽

角色類/介面關鍵方法
被觀察者ObservableaddObserver()、setChanged()、notifyObservers()
觀察者Observerupdate(Observable o, Object arg)

關鍵點: 必須先調用 setChanged() 設置內部標誌位,notifyObservers() 才會真正觸發觀察者的 update()。此設計避免無效通知。

案例一:基本數據變更通知

NumObservable 封裝整數 data,setData() 修改值後發送通知;NumObserver 接收並打印新值。

// 被觀察者
public class NumObservable extends Observable {
    private int data = 0;
    public void setData(int i) {
        data = i;
        setChanged();
        notifyObservers(); // arg 為 null
    }
}

// 觀察者
public class NumObserver implements Observer {
    public void update(Observable o, Object arg) {
        NumObservable src = (NumObservable) o;
        System.out.println("Data changed to " + src.getData());
    }
}

測試輸出:Data changed to 1 / 2 / 3

案例二:帶參數的差異化通知

業務常見需求:不同觀察者關注不同事件類型。利用 notifyObservers(Object arg) 傳遞標識,觀察者內部過濾。

public class NumsObservable extends Observable {
    public static final Integer ODD = 1, EVEN = 2;
    public void setData(int i) {
        data = i;
        Integer flag = (i & 0x0001) == 1 ? ODD : EVEN;
        setChanged();
        notifyObservers(flag); // 攜帶奇偶標識
    }
}

public class OddObserver implements Observer {
    public void update(Observable o, Object arg) {
        if (arg == NumsObservable.ODD) { // 僅處理奇數
            System.out.println("OddObserver: " + ((NumsObservable)o).getData());
        }
    }
}

測試中註冊 OddObserver 與 EvenObserver,輸出精準分流:Odd:1 / Even:2 / Odd:3。

最佳實踐與避坑指南

  1. 記得 setChanged():漏調是新手最常見錯誤,導致通知靜默失效。
  2. 傳遞不可變對象作為 arg:避免觀察者修改共享狀態引發併發問題。
  3. 及時移除觀察者:deleteObserver() 防止內存洩漏,尤其在生命週期不一致的組件間。
  4. 考慮替代方案:JDK 9 起標記棄用,現代項目推薦使用 PropertyChangeListener、Guava EventBus 或 Reactive Streams(RxJava/Project Reactor)獲得更強大的異步、背壓支持。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved