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

Java 設計模式之觀察者模式介紹

     編輯:Java 相關知識

觀察者模式:定義對象間一對多依賴,狀態變更自動通知

觀察者模式 屬於行為型模式。它定義對象間的一種一對多依賴關係,當一個對象 (Subject/Observable) 狀態發生改變時,所有依賴它的對象 (Observer) 都會得到通知並自動更新。廣泛用於事件處理系統、GUI、消息推送、模型-視圖分離 (MVC)。

核心角色

  • Subject (抽象主題/被觀察者):管理觀察者列表,提供註冊/移除/通知方法。JDK 提供 java.util.Observable 類 (已棄用) 和 java.util.Observer 接口 (已棄用),現代建議自定義或使用事件總線 (Guava EventBus, Spring ApplicationEvent)。
  • Observer (抽象觀察者):定義更新接口 update(Observable o, Object arg)。
  • ConcreteSubject / ConcreteObserver:具體實現。

代碼範例:商品價格變更通知


// 1. 自定義 Observable (替代已棄用的 JDK 類)
public class Product {
    private String name;
    private float price;
    private final List observers = new ArrayList<>();

    public void addObserver(Observer o) { observers.add(o); }
    public void removeObserver(Observer o) { observers.remove(o); }

    public void setPrice(float price) {
        this.price = price;
        notifyObservers(new PriceChangeEvent(this, price)); // 發送事件對象
    }

    private void notifyObservers(Object event) {
        for (Observer o : observers) {
            o.update(this, event);
        }
    }
    // getter...
}

// 2. 事件對象 (攜帶變更詳情)
public class PriceChangeEvent {
    private final Product product;
    private final float newPrice;
    public PriceChangeEvent(Product p, float price) { this.product = p; this.newPrice = price; }
    // getter...
}

// 3. 觀察者接口
public interface Observer {
    void update(Object source, Object event);
}

// 4. 具體觀察者:郵件通知、日誌記錄、緩存刷新
public class EmailNotifier implements Observer {
    @Override
    public void update(Object source, Object event) {
        if (event instanceof PriceChangeEvent) {
            PriceChangeEvent e = (PriceChangeEvent) event;
            System.out.println("發送郵件: 商品 " + e.getProduct().getName() + " 價格變為 " + e.getNewPrice());
        }
    }
}

public class CacheRefresher implements Observer {
    @Override
    public void update(Object source, Object event) {
        if (event instanceof PriceChangeEvent) {
            System.out.println("刷新商品緩存: " + ((PriceChangeEvent)event).getProduct().getName());
        }
    }
}

// 5. 客戶端
public class Client {
    public static void main(String[] args) {
        Product product = new Product("iPhone 15", 7999);
        product.addObserver(new EmailNotifier());
        product.addObserver(new CacheRefresher());

        product.setPrice(7799); // 觸發通知
    }
}

推模型 vs 拉模型

  • 推模型:notifyObservers(event) 直接傳遞變更數據 (如上例),觀察者被動接收。
  • 拉模型:notifyObservers() 僅通知,觀察者主動從 Subject 獲取感興趣數據。耦合度較高但數據傳輸可控。

現代替代方案

  • Spring ApplicationEvent:ApplicationEventPublisher 發布事件,@EventListener 監聽,支持異步、事務綁定。
  • Guava EventBus:輕量級進程內事件總線,基於註解 @Subscribe。
  • Reactive Streams (RxJava, Reactor):Observable/Flowable 流式處理,支持背壓、操作符組合。
  • 消息隊列:跨進程/分佈式場景 (Kafka, RabbitMQ)。

應用場景

  • GUI 事件監聽 (按鈕點擊、滑鼠移動)。
  • 股票行情推送、新聞訂閱。
  • 模型數據變更自動更新視圖 (MVC)。
  • 緩存失效通知、配置中心動態刷新。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved