觀察者模式(Observer Pattern)

1. 概述

  有時被稱作發佈/訂閱模式,觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。

2. 解決的問題

  將一個系統分割成一個一些類相互協作的類有一個不好的副作用,那就是需要維護相關對象間的一致性。我們不希望爲了維持一致性而使各類緊密耦合,這樣會給維護、擴展和重用都帶來不便。觀察者就是解決這類的耦合關係的。

3. 模式中的角色

  3.1 抽象主題(Subject):它把所有觀察者對象的引用保存到一個聚集裏,每個主題都可以有任何數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者對象。

  3.2 具體主題(ConcreteSubject):將有關狀態存入具體觀察者對象;在具體主題內部狀態改變時,給所有登記過的觀察者發出通知。

  3.3 抽象觀察者(Observer):爲所有的具體觀察者定義一個接口,在得到主題通知時更新自己。

  3.4 具體觀察者(ConcreteObserver):實現抽象觀察者角色所要求的更新接口,以便使本身的狀態與主題狀態協調。

4.代碼

用代碼模擬一個消息生產者(具體主題)的消息內容發生了更新,需要向他的多個消費者(具體觀察者)發出最新的消息的場景。

/**
 * 作爲一個具體主題,當message發生更新時,向他所有的觀察者發佈最新的消息
 * Created by yangjiachang on 2016/8/25.
 */
public class MessageProducer extends Observable{

    private String message;

    public void pushMessage(String msg){
        if (StringUtils.isBlank(msg)){
            throw new NullPointerException();
        }
        if (StringUtils.equals(message,msg)){
            return;
        }
        message = msg;
        System.out.println("發佈消息");
        //內部狀態發生改變
        setChanged();
        //向觀察者發佈最新消息
        notifyObservers();
    }

    public String getMessage() {
        return message;
    }
}

/**
 * 作爲具體觀察者,接受主題發送過來的消息,並完成自身業務邏輯
 * Created by yangjiachang on 2016/8/25.
 */
public class MessageConsumer implements Observer {

    public void update(Observable o, Object arg) {
        if(o instanceof MessageProducer){
            MessageProducer messageProducer = (MessageProducer)o;
            //獲取消息
            String message = messageProducer.getMessage();
            //處理業務邏輯
            view(message);
        }
    }

    private void view(String message){
        System.out.println("閱讀消息:"+message);
    }

public class Test {

   public static void main(String[] args){
      MessageProducer producer = new MessageProducer();
      producer.addObserver(new MessageConsumer());
      producer.addObserver(new MessageConsumer());
      producer.addObserver(new MessageConsumer());
      System.out.println("當前共有" + producer.countObservers() + "個觀察者");
      producer.pushMessage("您有一條新消息:aaa");
      producer.pushMessage("您有一條新消息:bbb");
   }
}
運行結果:

當前共有3個觀察者
發佈消息
閱讀消息:您有一條新消息:aaa
閱讀消息:您有一條新消息:aaa
閱讀消息:您有一條新消息:aaa
發佈消息
閱讀消息:您有一條新消息:bbb
閱讀消息:您有一條新消息:bbb
閱讀消息:您有一條新消息:bbb


通過以上的例子定義了一個消息生產者(主題),以及它的消費者(觀察者),先後發出了2條消息,均被消費者接收並完成閱讀。

這個例子中的具體主題就是MessageProducer類,他繼承了抽象主題Observable類;具體觀察者MessageConsumer類實現了抽象觀察者Observer接口。

下面我們通過源碼瞭解一下抽象主題Observable類,和抽象觀察者Observer接口。

Observable類中有2個變量,分別是:

    private boolean changed = false;
    private Vector<Observer> obs;
其中changed表示主題的內部是否發生了變化,通過setChanged()方法將changed賦值爲true,clearChanged()方法賦值爲false,hasChanged()方法查詢當前狀態;

obs記錄了該主題的觀察者有哪些,通過addObserver(Observer o)方法添加觀察者,deleteObserver(Observer o)方法刪除觀察者,countObserver()方法獲取當前觀察者數量。

通過notifyObserver方法向觀察者發佈主題內容。

具體觀察者只需要實現Observer接口中的update方法完成自身業務邏輯。


發佈了45 篇原創文章 · 獲贊 65 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章