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

Java 觀察者模式深度解析:自訂實作、java.util 支援與 AWT/Servlet/SAX 事件機制

     編輯:Java 相關知識

模式定義與別名

觀察者模式定義一對多依賴:主題 (Subject) 狀態變更時,自動通知所有觀察者 (Observer) 更新。別名:發布-訂閱、Model/View、Source/Listener、Dependents。

角色與類圖

  • Subject (抽象主題):管理觀察者清單,提供 attach()/detach()/notifyObservers()。
  • Observer (抽象觀察者):定義 update() 介面。
  • ConcreteSubject:具體狀態持有者,狀態改變呼叫 notifyObservers()。
  • ConcreteObserver:持有主題參考,實作 update() 同步狀態。

自訂實作範例

// Subject 介面
public interface Subject {
    void attach(Observer o);
    void detach(Observer o);
    void notifyObservers();
}

// ConcreteSubject 使用 Vector 管理觀察者
public class ConcreteSubject implements Subject {
    private Vector obs = new Vector<>();
    public void attach(Observer o) { obs.add(o); }
    public void detach(Observer o) { obs.remove(o); }
    public void notifyObservers() {
        for (Observer o : obs) o.update();
    }
}

// Observer 介面
public interface Observer { void update(); }

// ConcreteObserver
public class ConcreteObserver implements Observer {
    public void update() { /* 同步邏輯 */ }
}

JDK 內建支援:java.util.Observable / Observer

Observer 介面

package java.util;
public interface Observer {
    void update(Observable o, Object arg); // arg 可攜帶變更細節
}

Observable 類別核心方法

  • addObserver(Observer) / deleteObserver(Observer):註冊/移除。
  • setChanged():標記狀態已變更 (內部 changed flag)。
  • notifyObservers() / notifyObservers(Object arg):若 changed==true,複製觀察者陣列並逐一呼叫 update(this, arg),最後 clearChanged()。
  • hasChanged()、countObservers()、deleteObservers()。

使用範例:Watched / Watcher

public class Watched extends Observable {
    private String data;
    public void changeData(String d) {
        if (!data.equals(d)) { data = d; setChanged(); notifyObservers(); }
    }
    public String retrieveData() { return data; }
}

public class Watcher implements Observer {
    public Watcher(Watched w) { w.addObserver(this); }
    public void update(Observable o, Object arg) {
        System.out.println("Data changed to: " + ((Watched)o).retrieveData());
    }
}

// Client
Watched w = new Watched();
Observer watcher = new Watcher(w);
w.changeData("A"); // 通知
w.changeData("A"); // 未變更,不通知
w.changeData("B"); // 通知

輸出:
Data changed to: A
Data changed to: B

經典類比:菩薩淨瓶與守瓶龜

菩薩 (Observable) 將淨瓶拋入海中 → notifyObservers();守瓶龜 (Observer) 感知並駕瓶歸岸 → update()。生動詮釋「發布-訂閱」鬆耦合關係。

Java 事件機制皆基於觀察者模式

核心精神:介面抽象、動態註冊、同步通知。

優缺點權衡

優點

  • 主題與觀察者抽象耦合,可獨立演化、屬於不同抽象層級。
  • 支援廣播通訊,一對多通知無需修改主題。

缺點

  • 觀察者過多時通知延遲明顯。
  • 循環依賴導致遞迴通知、系統崩潰。
  • 異步通知需自行保證一致性。
  • 觀察者僅知「有變更」,不知「如何變更」 (需自行比對或攜帶 arg)。

相關模式

  • Memento (備忘錄):notifyObservers 內部複製觀察者陣列時隱性使用備忘錄保護迭代安全。
  • Mediator (中介者):可封裝複雜的觀察者網路拓撲。

思考題:媽媽煮飯叫吃飯

「媽媽,飯好叫我們」——媽媽是 Subject,孩子是 Observers。飯熟 (狀態變更) → 通知 → 孩子更新狀態 (準備吃飯) → 行動 (吃飯)。類圖同標準結構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
技術領域事件源 (Publisher)事件監聽器 (Subscriber)註冊方法
AWT/Swing (DEM)Component (Button 等)ActionListener, MouseListener 等addActionListener()
ServletServletContext, HttpSessionServletContextListener, HttpSessionAttributeListener@WebListener 或 web.xml
SAX2 XML 解析XMLReaderContentHandler, ErrorHandlersetContentHandler()