上一篇 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