OkHttp設(shè)計(jì)模式剖析(五)觀察者模式

上一篇 OkHttp設(shè)計(jì)模式剖析(四)享元模式

下一篇 OkHttp設(shè)計(jì)模式剖析(六)外觀模式

OKHTTP:

由大名鼎鼎的Square公司開發(fā)的網(wǎng)絡(luò)通信庫。

設(shè)計(jì)模式:

軟件開發(fā)中問題的解決套路。

觀察者模式簡介

定義:定義對象間一種一對的依賴關(guān)系,使得每當(dāng)一個(gè)對象改變狀態(tài),則所有依賴于它的對象都會得到廣播通知并被自動更新。

其實(shí)觀察者模式(Observer Pattern)叫做發(fā)布-訂閱模式更合適。發(fā)布者一旦更新消息,所有訂閱者都能收到。觀察者模式也很適用于UI事件觸發(fā)和偵聽,消息交換等場景
Observer和Observable是JDK中的內(nèi)置類型,若一個(gè)對象繼承了Observer類,那么這段代碼大概率用了觀察者模式。

OkHttp中WebSocket監(jiān)聽器中的觀察者模式

OkHttp中WebSocket的觀察者模式并不典型,它并不是一對多的觀察者模式。而是一個(gè)WebSocketListener監(jiān)聽一個(gè)Socket的觀察者模式,這種觀察者是基于回調(diào)函數(shù)處理的。
在一個(gè)連接WebSocket上的消息監(jiān)聽器Listener,所有回調(diào)都將在單個(gè)線程上調(diào)用,監(jiān)聽器遵循生命周期規(guī)則。源碼如下:

public interface WebSocketListener {
  // WebSocket 打開 則調(diào)用onOpen 
  void onOpen(WebSocket webSocket, Response response);
  // 接收到Server端發(fā)來的Message 則調(diào)用onMessage
  void onMessage(ResponseBody message) throws IOException;
  // 接收到Server端發(fā)來的Pong 則調(diào)用onPong
  void onPong(ByteString payload);
  // WebSocket 關(guān)閉 則調(diào)用onClose
  void onClose(int code, String reason);
  // WebSocket 錯(cuò)誤 則調(diào)用onFailure
  void onFailure(Throwable t, Response response);
}

定義WebSocketCall接口,源碼如下:

public interface WebSocketCall extends Cloneable {
  //返回啟動此調(diào)用的原始請求。
  Request request();
  // 監(jiān)聽器入隊(duì),安排在將來某個(gè)時(shí)間點(diǎn)執(zhí)行請求。
  void enqueue(WebSocketListener listener);

  // 取消請求
  void cancel();

  // 若此WebSocketCall入隊(duì),返回true
  boolean isExecuted();

  boolean isCanceled();

  WebSocketCall clone();

  interface Factory {
    WebSocketCall newWebSocketCall(Request request);
  }
}

此時(shí)監(jiān)聽器已經(jīng)成為訂閱者。WebSocket接口的實(shí)現(xiàn)類RealWebSocket若處于開啟狀態(tài),持續(xù)監(jiān)聽Socket接收消息。那么訂閱之后會有什么響應(yīng)呢?我們跳轉(zhuǎn)到實(shí)現(xiàn)WebSocketCall接口的RealWebSocketCall類,重點(diǎn)閱讀enqueue()函數(shù):

  @Override public void enqueue(final WebSocketListener listener) {
    Callback responseCallback = new Callback() { // 監(jiān)聽后必然得回調(diào)
      @Override public void onResponse(Call call, Response response) {
        StreamWebSocket webSocket;
        try {
          webSocket = create(response, listener);  
        } catch (IOException e) {
          listener.onFailure(e, response);
          return;
        }
        webSocket.loopReader();  // 開始輪訓(xùn)讀取消息
      }

      @Override public void onFailure(Call call, IOException e) {
        listener.onFailure(e, null);
      }
    };
    call.enqueue(responseCallback);
  }

回調(diào)函數(shù)是一種特殊的觀察者模式,是一種一對一的觀察者模式。

基于觀察者模式構(gòu)建的其他代碼

1、Android的BroadcastRecevier廣播機(jī)制
2、ListView中的notifyDataSetChanged()方法

Windows事件監(jiān)聽機(jī)制就是發(fā)布-訂閱模型

Windows桌面軟件一旦打開,都在監(jiān)聽鼠標(biāo),鍵盤等輸入設(shè)備給他傳遞的信息。下面的代碼舉了同時(shí)打開了PS和Word,監(jiān)聽輸入事件為例子:

public class Software implements Observer {
    
    public String softwareName;
    
    public Software(String softwareName) {
        this.softwareName = softwareName;
    }
    
    @Override
    public void update(Observable o,Object arg) {
        System.out.println(arg+"進(jìn)行判斷改事件是否操作于"+softwareName);
    }
    
    @Override
    public String toString() {
        return "軟件名:"+softwareName;
    }

}

public class WindowsEventListener extends Observable {
    
    public void postEvent(String content) {
        setChanged();
        notifyObservers(content);
    }

}

public class Main {

    public static void main(String[] args) {
        // 被觀察者
        WindowsEventListener wel = new WindowsEventListener();
        // 觀察者
        Software PS = new Software("PS");
        Software Word = new Software("Word");
        
        wel.addObserver(PS);
        wel.addObserver(Word);
        
        wel.postEvent("發(fā)生鼠標(biāo)事件");
        wel.postEvent("發(fā)生鍵盤事件");
        
    }

}
/* 輸出
發(fā)生鼠標(biāo)事件,Word進(jìn)行判斷這一事件是否操作于自身
發(fā)生鼠標(biāo)事件,PS進(jìn)行判斷這一事件是否操作于自身
發(fā)生鍵盤事件,Word進(jìn)行判斷這一事件是否操作于自身
發(fā)生鍵盤事件,PS進(jìn)行判斷這一事件是否操作于自身
*/

參考文獻(xiàn)

1、設(shè)計(jì)模式|菜鳥教程:https://www.runoob.com/design-pattern/design-pattern-tutorial.html
2、《Android源碼設(shè)計(jì)模式解析與實(shí)戰(zhàn)》何紅輝,關(guān)愛民著
3、隔壁老李頭:http://www.itdecent.cn/p/82f74db14a18

上一篇 OkHttp設(shè)計(jì)模式剖析(四)享元模式

下一篇 OkHttp設(shè)計(jì)模式剖析(六)外觀模式

All is well.

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容