設計模式之觀察者設計模式
阿新 • • 發佈:2018-11-20
原文首發於微信公眾號:jzman-blog,歡迎關注交流!
最近補一下設計模式相關的知識,關於觀察者設計模式主要從以下幾個方面來學習,具體如下:
- 什麼是觀察者設計模式
- 關鍵概念理解
- 通知觀察者的方式
- 觀察者模式的實現
- 觀察者模式的優缺點
- 使用場景
下面來一張本節內容的思維導圖,具體如下:
什麼是觀察者設計模式
觀察者模式(Observer)是軟體設計模式的一種,定義了物件之間一種一對多的關係,也就是當一個物件資料發生變化時,會通知與之依賴的其他物件,以相應其資料變化,這種當目標物件資料發生變化時,與之對應的觀察者物件
關鍵概念理解
觀察者設計模式中主要區分兩個概念:
- 觀察者:指觀察者物件,也就是訊息的訂閱者;
- 被觀察者:指要觀察的目標物件,也就是訊息的釋出者。
通知觀察者的方式
- 推:訊息以類似廣播的形式通知觀察者,觀察者只能被動、無條件接受;
- 拉:接收到被觀察者的通知,可以自主決定獲取訊息。
觀察者模式的實現
下面通過兩種方式實現觀察者設計模式的實現,具體如下:
- 手寫觀察者設計模式
- Java API 提供的觀察者設計模式 使用 Java API 提供的 Observer 和 Observeable 實現觀察者模式
1. 手寫觀察者模式
首先建立被觀察者,具體如下:
/**
* 觀察者要觀察的目標物件
* @author jzman
*/
public abstract class Subject {
protected ArrayList<Observer> observerList = new ArrayList<>();
//表示觀察者對目標物件(被觀察者)開始觀察
public void registerObserver(Observer obs) {
observerList.add(obs);
}
//表示取消某觀察者對目標物件(被觀察者)的觀察
public void unRegisterObserver(Observer obs) {
observerList.remove(obs);
}
//當目標物件(被觀察者)的狀態發生變化時,及時更新觀察者的狀態
public void notifyAllObserver(){
for (Observer observer : observerList) {
observer.update(this);
}
}
}
建立具體的被觀察者,具體如下:
/**
* 具體的目標物件(被觀察者)
* @author jzman
*/
public class ConcreteSubject extends Subject{
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
//當資料發生變化時通知其他的觀察者
notifyAllObserver();
}
}
然後,為了統一方便,定義觀察者介面,具體如下:
/**
* 觀察者統一介面
* @author jzman
*/
public interface Observer {
void update(Subject subject);
}
然後,建立具體的觀察者,具體如下:
/**
* 具體的觀察者
* @author jzman
*/
public class ConcreteObserver implements Observer{
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
@Override
public void update(Subject subject) {
//獲取目標物件的資料變化,同時更新當前觀察者
ConcreteSubject concreteSubject = (ConcreteSubject)subject;
state = concreteSubject.getState();
}
}
最後,測試觀察者設計模式,具體如下:
/**
* Main
* @author jzman
*/
public class Client {
public static void main(String[] args) {
//建立具體的目標物件(被觀察者)
ConcreteSubject concreteSubject = new ConcreteSubject();
//建立多個具體的觀察者
ConcreteObserver obs1 = new ConcreteObserver();
ConcreteObserver obs2 = new ConcreteObserver();
ConcreteObserver obs3 = new ConcreteObserver();
//讓觀察者觀察目標物件(被觀察者)的資料變化
concreteSubject.observerList.add(obs1);
concreteSubject.observerList.add(obs2);
concreteSubject.observerList.add(obs3);
//改變某個目標物件(被觀察者)的資料
concreteSubject.setState(10);
//觀察者資料是否與被觀察者資料變化一致
System.out.println("觀察者obs1:"+obs1.getState());
System.out.println("觀察者obs2:"+obs2.getState());
System.out.println("觀察者obs3:"+obs3.getState());
}
}
顯然,執行結果肯定如下:
觀察者obs1:10
觀察者obs2:10
觀察者obs3:10
通過對目標物件資料的改變,更新了與之相對應的觀察者的資料,實現了訊息的訂閱和傳送。
2. Java API 提供的觀察者設計模式
Java API 提供的觀察者設計模式主要通過 Observer 和 Observeable 來實現,首先建立一個類繼承 Observeable 作為被觀察者,具體如下:
/**
* 被觀察者(目標物件)
* @author jzman
*/
public class ConcreteSubject extends Observable{
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
//表示資料已經發生變化
setChanged();
//具體的目標物件資料變化的時候通知觀察者
notifyObservers(state);
}
}
然後,建立一個類繼承 Observer 作為觀察者,具體如下:
/**
* 觀察者
* @author jzman
*/
public class ConcreteObserver implements Observer{
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
@Override
public void update(Observable arg0, Object arg1) {
ConcreteSubject concreteSubject = (ConcreteSubject) arg0;
//根據目標物件(被觀察者)的資料變化更新當前觀察者的資料
this.state = concreteSubject.getState();
}
}
最後,測試觀察者設計模式,具體如下:
/**
* 測試觀察者設計模式
* @author jzman
*/
public class Client {
public static void main(String[] args) {
ConcreteSubject concreteSubject = new ConcreteSubject();
ConcreteObserver obs1 = new ConcreteObserver();
ConcreteObserver obs2 = new ConcreteObserver();
ConcreteObserver obs3 = new ConcreteObserver();
concreteSubject.addObserver(obs1);
concreteSubject.addObserver(obs2);
concreteSubject.addObserver(obs3);
concreteSubject.setState(100);
System.out.println("觀察者obs1:"+obs1.getState());
System.out.println("觀察者obs2:"+obs2.getState());
System.out.println("觀察者obs3:"+obs3.getState());
}
}
顯然,執行結果肯定如下:
觀察者obs1:100
觀察者obs2:100
觀察者obs3:100
觀察者模式的優缺點
- 優點:觀察者與被觀察者抽象耦合,可定義一種穩定的訊息觸發機制。
- 缺點:如果被觀察者有多個間接的觀察者,訊息的傳遞將消耗更多時間,如果觀察者與被觀察者之間迴圈依賴,最終會導致系統崩潰。
使用場景
觀察者設計模式在開發中使用比較廣泛,主要有以下幾個場景,具體如下:
- 如遊戲、聊天等過程中訊息的從服務端轉發給客戶端的過程
- Android 中的廣播機制以及 ListView 中通知資料發生變化時也是觀察者設計模式
- 訂閱類相關的系統,如當訂閱的主題有更新,訂閱者就會同步訂閱的文章。
可以選擇關注微信公眾號:jzman-blog 獲取最新更新,一起交流學習!