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

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章