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

Java 觀察者模式實戰:鬆耦合事件通知機制,內置 Observable 與自定義實現

     編輯:Java 相關知識

觀察者模式定義對象間一對多依賴,當主題狀態改變時自動通知所有觀察者。本文展示自定義實現(推薦)與 JDK 內置 Observable/Observer(已棄用)兩種方式,並解析 Servlet Filter、消息隊列中的實戰應用。

自定義實現(推薦)

// 觀察者介面
interface Observer {
    void update(Subject subject);
}

// 主題(被觀察者)抽象類
abstract class Subject {
    private List<Observer> observers = new ArrayList<>();
    public void addObserver(Observer o) { observers.add(o); }
    public void removeObserver(Observer o) { observers.remove(o); }
    protected void notifyAllObservers() {
        for (Observer o : observers) o.update(this);
    }
}

// 具體主題:新聞廣播
class NewsSubject extends Subject {
    private String news;
    public void setNews(String news) {
        this.news = news;
        System.out.println("廣播發布新聞:" + news);
        notifyAllObservers();
    }
    public String getNews() { return news; }
}

// 具體觀察者:訂閱用戶
class UserObserver implements Observer {
    private String name;
    public UserObserver(String name) { this.name = name; }
    public void update(Subject subject) {
        String news = ((NewsSubject)subject).getNews();
        System.out.println(name + " 收到新聞:" + news + " → 做出反應");
    }
}

// 客戶端
public class Demo {
    public static void main(String[] args) {
        NewsSubject subject = new NewsSubject();
        subject.addObserver(new UserObserver("用戶A"));
        subject.addObserver(new UserObserver("用戶B"));
        subject.addObserver(new UserObserver("用戶C"));
        subject.setNews("今日天氣晴朗");
    }
}

/* 輸出:
廣播發布新聞:今日天氣晴朗
用戶A 收到新聞:今日天氣晴朗 → 做出反應
用戶B 收到新聞:今日天氣晴朗 → 做出反應
用戶C 收到新聞:今日天氣晴朗 → 做出反應
*/

JDK 內置實現(Java 9 標記棄用)


// 繼承 java.util.Observable
class JdkNews extends Observable {
    public void setNews(String news) {
        setChanged();        // 必須調用,標記狀態已變
        notifyObservers(news); // 推模式:直接傳遞數據
    }
}

// 實現 java.util.Observer
class JdkUser implements Observer {
    public void update(Observable o, Object arg) {
        System.out.println("JDK觀察者收到:" + arg);
    }
}

// 使用
JdkNews news = new JdkNews();
news.addObserver(new JdkUser());
news.setNews("JDK 內置觀察者");

棄用原因:Observable 是類而非介面,限制復用;notifyObservers 同步阻塞;無線程安全保證。建議自定義或使用事件總線。

企業級應用場景

  • Servlet Filter 鏈:FilterChain.doFilter 類似通知下一個觀察者
  • 分布式消息隊列:Kafka/RocketMQ Consumer Group 即觀察者集合
  • Spring 事件機制:ApplicationEventPublisher + @EventListener
  • GUI 事件監聽:按鈕點擊、鼠標移動
  • 模型視圖分離:Model 變更通知 View 更新

進階優化方向

  1. 異步通知:ExecutorService 提交通知任務,避免阻塞發布者
  2. 事件總線:Guava EventBus / Spring ApplicationEvent 解耦主題與觀察者註冊
  3. 弱引用觀察者:防止內存洩漏(WeakReference<Observer>)
  4. 過濾通知:觀察者註冊時聲明關注的事件類型,精準推送

觀察者 vs 發布訂閱

維度觀察者模式發布訂閱模式
耦合度主題持有觀察者引用通過事件通道/總線完全解耦
同步性通常同步通常異步
跨進程不支援支援(消息中間件)

觀察者模式是事件驅動架構的基石,掌握其核心與變體,能構建高內聚低耦合的系統。

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