定義
定義對象間的一種一對多依賴關系,使得每當一個對象狀態發生改變時,其相關依賴對象皆得到通知并被自動更新。觀察者模式又叫做發布-訂閱(Publish-Subscribe)模式、模型-視圖(Model-View)模式、源-監聽器(Source-Listener)模式或從屬者(Dependents)模式。
模式結構
觀察者模式包含如下角色:
- Subject: 目標
- ConcreteSubject: 具體目標
- Observer: 觀察者
- ConcreteObserver: 具體觀察者
UML圖
ObserverUML.png
代碼實現
Subject.java
/**
* 抽象目標者
*/
public abstract class Subject {
// 保存注冊的觀察者對象
private List<Observer> mObservers = new ArrayList<>();
//注冊觀察者對象
public void attach(Observer observer) {
mObservers.add(observer);
System.out.println("Attached an observer");
}
//注銷觀察者對象
public void detach(Observer observer) {
mObservers.remove(observer);
}
// 通知所有注冊的觀察者對象
public void nodifyObservers(String newState) {
for (Observer observer : mObservers) {
observer.update(newState);
}
}
}
ConcreteSubject.java
/**
* 具體目標者
*/
public class ConcreteSubject extends Subject {
private String state;
public String getState() {
return state;
}
public void change(String newState) {
state = newState;
System.out.println("ConcreteSubject State:" + state);
//狀態發生改變,通知觀察者
nodifyObservers(state);
}
}
Observer.java
/**
* 觀察者
*/
public interface Observer {
void update(String state);
}
ConcreteObserver.java
/**
*具體觀察者
*/
public class ConcreteObserver implements Observer {
// 觀察者狀態
private String observerState;
@Override
public void update(String state) {
// 更新觀察者狀態,讓它與目標狀態一致
observerState = state;
System.out.println("ConcreteObserver State :" + observerState);
}
}
test
public class MyClass {
public static void main(String[] args) {
// 創建目標對象
ConcreteSubject concreteSubject = new ConcreteSubject();
// 創建觀察者對象
Observer observer = new ConcreteObserver();
// 將觀察者對象注冊到目標對象上
concreteSubject.attach(observer);
// 改變目標對象的狀態
concreteSubject.change("I change");
}
}
運行結果
模式分析
觀察者模式描述了如何建立對象與對象之間的依賴關系,如何構造滿足這種需求的系統。
這一模式中的關鍵對象是觀察目標和觀察者,一個目標可以有任意數目的與之相依賴的觀察者,一旦目標的狀態發生改變,所有的觀察者都將得到通知。
作為對這個通知的響應,每個觀察者都將即時更新自己的狀態,以與目標狀態同步,這種交互也稱為發布-訂閱(publish-subscribe)。目標是通知的發布者,它發出通知時并不需要知道誰是它的觀察者,可以有任意數目的觀察者訂閱它并接收通
觀察模式的優點
觀察者模式可以實現表示層和數據邏輯層的分離,并定義了穩定的消息更新傳遞機制,抽象了更新接口,使得可以有各種各樣不同的表示層作為具體觀察者角色。
觀察者模式在觀察目標和觀察者之間建立一個抽象的耦合。
觀察者模式支持廣播通信。
觀察者模式符合“開閉原則”的要求。
觀察模式的缺點
如果一個觀察目標對象有很多直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。
如果在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發它們之間進行循環調用,可能導致系統崩潰。
觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎么發生變化的,而僅僅只是知道觀察目標發生了變化。