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

前言

最近查看OkHttp 請(qǐng)求框架,發(fā)現(xiàn)里面過濾器用的非常靈活,而其整個(gè)設(shè)計(jì)模式就是采用責(zé)任鏈模式來設(shè)計(jì)的,這篇博客主要用來討論一下責(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)景來作說明:

假設(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 的返回值來確定下一個(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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 我很慌,可是慌容易出錯(cuò),所以一直在調(diào)節(jié),今晚約定金會(huì)員來體驗(yàn)課程的時(shí)候,很多會(huì)員都在約課,這在很大的程度上給了我鼓...
    敲可愛的夏天吖閱讀 180評(píng)論 0 3
  • 今天晚上放學(xué)以后,兒子高興地說:“媽媽,我的作業(yè)在學(xué)校都寫完了。” “都檢查過了嗎?”我問。“檢查過了,都對(duì)了。"...
    李韶航媽媽閱讀 177評(píng)論 0 0
  • 婚姻并不是簡(jiǎn)單的買房結(jié)婚生子,而是為了在這個(gè)浮躁的社會(huì)上,還有一處地方能讓你心生暖意,讓你覺得人間值得,對(duì)待婚姻,...
    老剁手閱讀 212評(píng)論 0 0
  • 似倉(cāng)促的敲門聲,又似著急呼喊聲,把我從夢(mèng)中驚醒過來,睜開雙眼,僵直著眼睛,努力回憶著,又想不起什么事情,又好像要發(fā)...
    那條戀戀不舍的路閱讀 458評(píng)論 4 2

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