OkHttp之責(zé)任鏈模式設(shè)計(jì)與使用

前言

最近查看OkHttp 請(qǐng)求框架膝晾,發(fā)現(xiàn)里面過濾器用的非常靈活币喧,而其整個(gè)設(shè)計(jì)模式就是采用責(zé)任鏈模式來(lái)設(shè)計(jì)的,這篇博客主要用來(lái)討論一下責(zé)任鏈相關(guān)設(shè)計(jì)與使用。

責(zé)任鏈模式

一個(gè)事件需要經(jīng)過多個(gè)對(duì)象處理是一個(gè)挺常見的場(chǎng)景蜓萄,譬如采購(gòu)審批流程,請(qǐng)假流程澄峰。同樣網(wǎng)絡(luò)請(qǐng)求中也存在一些列的流程嫉沽,這也是OkHttp采用該模式的主要原因。下面以一個(gè)采購(gòu)場(chǎng)景來(lái)作說(shuō)明:

假設(shè)公司要采購(gòu)一批物料俏竞,采購(gòu)流程一般是如下圖:
采購(gòu).jpg
采購(gòu)員->主管->經(jīng)理->總經(jīng)理這是一個(gè)完整的采購(gòu)流程绸硕。

代碼實(shí)現(xiàn):

Employee

public class Employee {
    private String name;
    private String msg;
    private int price;
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}

ApplyFilter

public interface ApplyFilter {
    boolean doFilter(Employee employee,ApplyFilterChain chain);
}

ApplyFilterChain

 public class ApplyFilterChain implements ApplyFilter {
    List<ApplyFilter> filters = new ArrayList<>();
    int index = 0;
    public ApplyFilterChain add(ApplyFilter applyFilter){
        filters.add(applyFilter);
        return this;
    }

    @Override
    public boolean doFilter(Employee employee,ApplyFilterChain chain) {
        if (index>=filters.size()) return false;
        ApplyFilter filter = filters.get(index);
        index ++;
        filter.doFilter(employee,chain);
        return true;
    }
}

SupervisorApplyFilter


/**
 * 主管審批
 */
public class SupervisorApplyFilter implements  ApplyFilter{

    @Override
    public boolean doFilter(Employee employee,ApplyFilterChain chain) {
        if (employee.getPrice()<=100){
            System.out.println("資金小于100主管審批通過,流程結(jié)束");
            employee.setMsg(employee.getMsg()+"資金小于100主管審批通過魂毁,流程結(jié)束");
            return false;
        }else {
            System.out.println("資金大于100主管請(qǐng)經(jīng)理審批");
            employee.setMsg(employee.getMsg()+"資金大于100主管請(qǐng)經(jīng)理審批->");
            chain.doFilter(employee,chain);
            return true;
        }
    }
}

ManagerApplyFilter


/**
 * 經(jīng)理審批
 */

public class ManagerApplyFilter implements  ApplyFilter{

    @Override
    public boolean doFilter(Employee employee ,ApplyFilterChain chain) {
        if (employee.getPrice()<=500){
            System.out.println("資金小于500經(jīng)理審批通過玻佩,流程結(jié)束");
            employee.setMsg(employee.getMsg()+"資金小于500經(jīng)理審批通過,流程結(jié)束");
            return false;
        }else {
            System.out.println("資金大于500經(jīng)理請(qǐng)總經(jīng)理審批");
            employee.setMsg(employee.getMsg()+"資金大于500經(jīng)理請(qǐng)總經(jīng)理審批->");
            chain.doFilter(employee,chain);
            return true;
        }
    }
}

GeneralManagerApplyFilter

/**
 * 總經(jīng)理審批
 */

public class GeneralManagerApplyFilter implements  ApplyFilter{
    @Override
    public boolean doFilter(Employee employee ,ApplyFilterChain chain) {
        if (employee.getPrice()<=5000){
            System.out.println("資金小于5000總經(jīng)理審批通過席楚,流程結(jié)束");
            employee.setMsg(employee.getMsg()+"資金小于5000總經(jīng)理審批通過夺蛇,流程結(jié)束");
            return false;
        }else {
            System.out.println("資金大于5000, 總經(jīng)理需要開會(huì)討論,流程結(jié)束");
            employee.setMsg(employee.getMsg()+"資金大于5000, 總經(jīng)理需要開會(huì)討論酣胀,流程結(jié)束");
            return true;
        }
    }
}

以上為一個(gè)完整的chain如果中間某個(gè)環(huán)節(jié)可以結(jié)束該流程,則后續(xù)的流程不用處理娶聘,這也是通過doFilter 的返回值來(lái)確定下一個(gè)流程是否繼續(xù)闻镶,這個(gè)是一個(gè)遞歸的思想,也是比較難以理解的地方丸升。
Main

public class Main {

    public static void main(String[] args) {
        Employee employee = new Employee();
        employee.setMsg("物料采購(gòu)申請(qǐng)->");
        employee.setPrice(10);
        ApplyFilterChain applyFilterChain = new ApplyFilterChain();
        applyFilterChain.add(new SupervisorApplyFilter()).add(new ManagerApplyFilter()).add(new GeneralManagerApplyFilter());
        applyFilterChain.doFilter(employee,applyFilterChain);
        System.out.println(employee.getMsg());
    }
}

得出的結(jié)果如下:

資金小于100主管審批通過铆农,流程結(jié)束
物料采購(gòu)申請(qǐng)->資金小于100主管審批通過,流程結(jié)束

以上是關(guān)于責(zé)任鏈模式的使用狡耻。

3 OkHttp

關(guān)于OkHttp 中過濾器的問題可以查看到RealCall類中:

 Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));

    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
  }

其不斷添加過濾器墩剖,但最后的過濾器為CallServerInterceptor由此可以得出結(jié)論,最終請(qǐng)求網(wǎng)絡(luò)等想過操作夷狰,就是在該類中進(jìn)行岭皂,查看代碼果真如此。
以上是關(guān)于在OkHttp中發(fā)現(xiàn)的責(zé)任鏈模式的使用沼头,其詳細(xì)介紹可以參考設(shè)計(jì)模式 | 責(zé)任鏈模式及典型應(yīng)用這篇文章寫得比較清楚爷绘。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市进倍,隨后出現(xiàn)的幾起案子土至,更是在濱河造成了極大的恐慌,老刑警劉巖猾昆,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陶因,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡垂蜗,警方通過查閱死者的電腦和手機(jī)楷扬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門解幽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人毅否,你說(shuō)我怎么就攤上這事亚铁。” “怎么了螟加?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵徘溢,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我捆探,道長(zhǎng)然爆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任黍图,我火速辦了婚禮曾雕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘助被。我一直安慰自己剖张,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布揩环。 她就那樣靜靜地躺著搔弄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丰滑。 梳的紋絲不亂的頭發(fā)上顾犹,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音褒墨,去河邊找鬼炫刷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛郁妈,可吹牛的內(nèi)容都是我干的浑玛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼噩咪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼锄奢!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起剧腻,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拘央,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后书在,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灰伟,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了栏账。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帖族。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖挡爵,靈堂內(nèi)的尸體忽然破棺而出竖般,到底是詐尸還是另有隱情,我是刑警寧澤茶鹃,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布涣雕,位于F島的核電站,受9級(jí)特大地震影響闭翩,放射性物質(zhì)發(fā)生泄漏挣郭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一疗韵、第九天 我趴在偏房一處隱蔽的房頂上張望兑障。 院中可真熱鬧,春花似錦蕉汪、人聲如沸流译。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)福澡。三九已至,卻和暖如春宛渐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背眯搭。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工窥翩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鳞仙。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓寇蚊,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親棍好。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仗岸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 我很慌,可是慌容易出錯(cuò)借笙,所以一直在調(diào)節(jié)扒怖,今晚約定金會(huì)員來(lái)體驗(yàn)課程的時(shí)候,很多會(huì)員都在約課业稼,這在很大的程度上給了我鼓...
    敲可愛的夏天吖閱讀 159評(píng)論 0 3
  • 今天晚上放學(xué)以后盗痒,兒子高興地說(shuō):“媽媽,我的作業(yè)在學(xué)校都寫完了低散「┑耍” “都檢查過了嗎?”我問骡楼。“檢查過了稽鞭,都對(duì)了鸟整。"...
    李韶航媽媽閱讀 120評(píng)論 0 0
  • 婚姻并不是簡(jiǎn)單的買房結(jié)婚生子,而是為了在這個(gè)浮躁的社會(huì)上朦蕴,還有一處地方能讓你心生暖意篮条,讓你覺得人間值得,對(duì)待婚姻梦重,...
    老剁手閱讀 184評(píng)論 0 0
  • 似倉(cāng)促的敲門聲兑燥,又似著急呼喊聲,把我從夢(mèng)中驚醒過來(lái)琴拧,睜開雙眼降瞳,僵直著眼睛,努力回憶著蚓胸,又想不起什么事情挣饥,又好像要發(fā)...
    那條戀戀不舍的路閱讀 380評(píng)論 4 2