banner
jzman

jzman

Coding、思考、自觉。
github

觀察者設計模式

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

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

什麼是觀察者設計模式#

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

關鍵概念理解#

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

  • 觀察者:指觀察者物件,也就是消息的訂閱者
  • 被觀察者:指要觀察的目標物件,也就是消息的發布者

通知觀察者的方式#

當被被觀察者數據發生變化時,主要通過兩種方式通知觀察者,具體如下:

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

觀察者模式的實現#

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

  1. 手寫觀察者設計模式
  2. Java API 提供的觀察者設計模式 使用 Java API 提供的 Observer 和 Observeable 實現觀察者模式

手寫觀察者模式#

首先創建被觀察者,具體如下:

/**
 * 觀察者要觀察的目標物件
 * @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

通過對目標物件數據的改變,更新了與之相對應的觀察者的數據,實現了消息的訂閱和發送。

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 中通知數據發生變化時也是觀察者設計模式
  • 訂閱類相關的系統,如當訂閱的主題有更新,訂閱者就會同步訂閱的文章。

觀察者設計模式到此結束。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。