觀察者模式(Observer Pattern)也稱發佈訂閱模式,它是一種在項目中經常使用的模式。 定義: 定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新。 觀察者模式的類圖如下所示。 觀察者模式具體有以下4個角色。 抽象主題(Subject)角 ...
觀察者模式(Observer Pattern)也稱發佈訂閱模式,它是一種在項目中經常使用的模式。
定義:
- 定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新。
觀察者模式的類圖如下所示。
觀察者模式具體有以下4個角色。
- 抽象主題(Subject)角色:又稱為“被觀察者”,可以增加和刪除觀察者對象。
- 抽象觀察者(Observer)角色:為所有具體觀察者定義一個介面,在得到主題的通知時更新自己。
- 具體主題(Concrete Subject)角色:又稱“具體被觀察者”,它將有關狀態存入具體觀察者對象,當它改變時,給所有登記過的觀察者發出通知。
- 具體觀察者(Concrete Observer)角色:實現抽象觀察者所有的更新介面,以便使自身狀態與主題狀態相協調。
Subject.java
public interface Subject { // 登記一個新的觀察者 public void attach(Observer obs); // 刪除一個登記過的觀察者 public void detach(Observer obs); // 通知所有登記過的觀察者對象 public void notifyObserver(); }
Observer.java
public interface Observer { // 更新方法 public void update(); }
ConcreteSubject.java
public class ConcreteSubject implements Subject { private Vector<Observer> obsVector = new Vector<Observer>(); @Override public void attach(Observer obs) { obsVector.add(obs); } @Override public void detach(Observer obs) { obsVector.remove(obs); } @Override public void notifyObserver() { for (Observer obs : obsVector) { obs.update(); } } public Enumeration<Observer> observers() { return obsVector.elements(); } // 業務方法,改變狀態 public void change() { this.notifyObserver(); } }
ConcreteObserver.java
public class ConcreteObserver implements Observer { @Override public void update() { System.out.println("收到通知,併進行處理"); } }
Client.java
public class Client { public static void main(String[] args) { // 創建一個主題對象(被觀察者) ConcreteSubject subject = new ConcreteSubject(); // 創建一個觀察者 Observer obs = new ConcreteObserver(); // 登記觀察者 subject.attach(obs); // 改變狀態 subject.change(); } }
優點:
- 觀察者與被觀察者之間是抽象耦合,它們屬不同的抽象化層次,且都很容易擴展。
- 支持廣播通信。被觀察者向所有登記過的觀察者發出通知,這就是一個觸發機制,形成一個觸發鏈。
缺點:
- 一個主題有多個直接或間接觀察者,通知所有觀察者會花費很多時間,且開發和調試都比較困難。
- 如果主題之間有迴圈依賴,被觀察者會觸發它們之間進行迴圈調用,導致系統崩潰。
- 如果對觀察者的通知是通過另外的線程進行非同步投遞,系統必須保證投遞的順序執行。
- 雖然觀察者模式可以隨時使觀察者知道所觀察的對象發生了變化,但是觀察者模式沒有提供相應的機制使觀察者知道所觀察的對象是如何發生變化。
應用場景:
- 關聯行為場景。
- 事件多級觸發場景。
- 跨系統的消息交換場景,如消息隊列的處理機制。
註意事項:
- 廣播鏈的問題一個觀察者可以有雙重身份,既是觀察者又是被觀察者,廣播鏈一旦建立,邏輯就比較複雜,可給你的維護性非常差。一般在一個觀察者模式中最多出現一個對象既是觀察者也是被觀察者,這樣消息最多轉發一次(傳遞兩次)較易控制。
- 非同步處理的問題。非同步處理就要考慮線程安全和隊列問題。
引用:
青島東合信息技術有限公司 . 設計模式(Java版) . 電子工業出版社,2012,149-152.