23天學習23種設計模式——觀察者模式

前言

在日常生活中,比如我們訂閱報紙或者訂牛奶。或者在網絡上,RSS方式訂閱別人的博客,微博follow某人,以及現在很火的即刻app。都是采取的訂閱的模式。當我們需要報紙,牛奶,以及查看別人博客/微博,或是某種主題的消息,我們只需采取訂閱的方式在發(fā)布方注冊一下即可。當我們不需要的時候,只要取消訂閱就可以了。在軟件開發(fā)中,同樣有利用這種原理的設計模式——觀察者模式。

是什么

觀察者模式(Observer Pattern):定義對象之間的一種一對多依賴關系,使得每當一個對象狀態(tài)發(fā)生改變時,其相關依賴對象都得到通知并被自動更新。

觀察者模式的別名包括發(fā)布-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監(jiān)聽器(Source/Listener)模式或從屬者(Dependents)模式。觀察者模式是一種對象行為型模式。

下圖就是觀察者模式結構圖:

有如下角色:

  • Subject: 目標
  • ConcreteSubject:具體目標
  • Observer: 觀察者
  • ConcreteObserver:具體觀察者
觀察者模式結構圖

為什么

還是以日常生活舉例,當我們想要查看某人的博客是否有更新的時候。我們可以直接在瀏覽器中輸入博客地址進行查看。但是這樣一種方式,往往效率不高。有可能幾天內都沒有更新。但是如果我們采用RSS方式訂閱的話,我們能在第一事件收到對方博客更新的消息。其他時候,我們可以處理別的事物,而不用主動查看是否有更新。同理,在軟件開發(fā)中。一些對象如果對對象A的狀態(tài)的變化感興趣,采用觀察者模式來訂閱它的狀態(tài)更新,這樣就不用持有對象A的引用了。降低了對象之間的耦合。

怎么做

首先是主題Subject類的實現,它使用集合持有訂閱者,訂閱者通過attach方法訂閱主題,detach方法取消訂閱,當主題的state發(fā)生變化時,通過notifyObservers通知訂閱者,主題狀態(tài)有更新:

/**
 * 主題,被觀察對象
 */
public class Subject {

    private List<Observer> observers = new ArrayList<>();//訂閱者鏈表

    private int state;//主題狀態(tài)

    public void attach(Observer observer){
        if(observer!=null){
            observers.add(observer);
        }
    }

    public void detach(Observer observer){
        observers.remove(observer);
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        notifyObservers();
    }

    public void notifyObservers(){
        for(Observer observer:observers){
            observer.update(this);
        }
    }
}


然后時訂閱者類的實現,一般是一個抽象類或者接口:

/**
 * 觀察者
 */
public interface Observer {

    void update(Subject subject);

}

接著時具體觀察者類的實現,在update方法中對主題狀態(tài)改變進行具體操作:

public class BinaryObserver implements Observer {
    @Override
    public void update(Subject subject) {
        System.out.println("Binary String:"+Integer.toBinaryString(subject.getState()));
    }
}

public class HexObserver implements Observer {
    @Override
    public void update(Subject subject) {
        System.out.println("Hex String:"+Integer.toHexString(subject.getState()));
    }
}

public class OctalObserver implements Observer {
    @Override
    public void update(Subject subject) {
        System.out.println("Octal String:"+Integer.toOctalString(subject.getState()));
    }
}

最后,我們寫個Client類看看具體應用:

public class Client {
    public static void main(String[] args) {

        Subject subject = new Subject();

        HexObserver hexObserver = new HexObserver();
        OctalObserver octalObserver = new OctalObserver();
        BinaryObserver binaryObserver = new BinaryObserver();

        //觀察者訂閱主題
        subject.attach(hexObserver);
        subject.attach(octalObserver);
        subject.attach(binaryObserver);

        System.out.println("Set state:15");
        subject.setState(15);//設置狀態(tài)

        System.out.println("-----------------");
        //取消訂閱主題
        subject.detach(octalObserver);
        System.out.println("Set state:24");
        subject.setState(24);//改變狀態(tài)


    }
}

運行結果:


運行結果
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1 場景問題# 1.1 訂閱報紙的過程## 來考慮實際生活中訂閱報紙的過程,這里簡單總結了一下,訂閱報紙的基本流程...
    七寸知架構閱讀 4,807評論 5 57
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,001評論 25 709
  • 純粹是個人學習總結,如有不對的地方請吐槽。 設計模式參考地址:http://www.cnblogs.com/mao...
    junwu_123閱讀 758評論 0 0
  • 設計模式匯總 一、基礎知識 1. 設計模式概述 定義:設計模式(Design Pattern)是一套被反復使用、多...
    MinoyJet閱讀 4,091評論 1 15
  • 今天已是8月最后一篇作業(yè),每次都是交作業(yè)這天,下午四點準時敲鍵盤。 如果有已經構思好的話題,那敲起來很順利,啪啪幾...
    少東閱讀 438評論 0 2

友情鏈接更多精彩內容