1. 程式人生 > >設計模式之觀察者設計模式

設計模式之觀察者設計模式

原文首發於微信公眾號:jzman-blog,歡迎關注交流!

最近補一下設計模式相關的知識,關於觀察者設計模式主要從以下幾個方面來學習,具體如下:

  1. 什麼是觀察者設計模式
  2. 關鍵概念理解
  3. 通知觀察者的方式
  4. 觀察者模式的實現
  5. 觀察者模式的優缺點
  6. 使用場景

下面來一張本節內容的思維導圖,具體如下:

這裡寫圖片描述

什麼是觀察者設計模式

觀察者模式(Observer)是軟體設計模式的一種,定義了物件之間一種一對多的關係,也就是當一個物件資料發生變化時,會通知與之依賴的其他物件,以相應其資料變化,這種當目標物件資料發生變化時,與之對應的觀察者物件

資料隨之發生變化的,具有一對多通知關係的設計模式叫做觀察者設計模式

關鍵概念理解

觀察者設計模式中主要區分兩個概念:

  • 觀察者:指觀察者物件,也就是訊息的訂閱者
  • 被觀察者:指要觀察的目標物件,也就是訊息的釋出者

通知觀察者的方式

  • :訊息以類似廣播的形式通知觀察者,觀察者只能被動、無條件接受;
  • :接收到被觀察者的通知,可以自主決定獲取訊息。

觀察者模式的實現

下面通過兩種方式實現觀察者設計模式的實現,具體如下:

  1. 手寫觀察者設計模式
  2. 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 獲取最新更新,一起交流學習!
這裡寫圖片描述