OkHttp学习(五) 3.10.0版本源码阅读之责任链设计模式

系列文章

OkHttp学习(一) OSI七层模型和TCP四层模型
OkHttp学习(二) 3.10.0版本的简单使用及其流程梳理
OkHttp学习(三) 3.10.0版本源码阅读之线程池
OkHttp学习(四) 3.10.0版本源码阅读之构建者设计模式
OkHttp学习(五) 3.10.0版本源码阅读之责任链设计模式
OkHttp学习(六) 3.10.0版本源码中的拦截器
OkHttp学习(七) 手写OkHttp之框架搭建
OkHttp学习(八) 手写OkHttp之网络请求实现
OkHttp学习(九) OkHttp的连接池手写实现

OkHttp中使用的责任链模式

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);
  }

多个拦截器组成了责任链中每个环节。 成链的关键就是chain.proceed方法中,又new了一自己next,用来调用处理者。 就这么重复调用RealInterceptorChain的proceed方法,形成了链。代码如下:

    // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);

RealInterceptorChain的proceed从构造方法传入的interceptors和index索引找到当前需要的拦截器。new
了一个next对象,interceptors还是同一个,但是index索引加了1,这么一来,这个next这个对象interceptors.get(index);的时候,就是next的拦截器了。
Interceptor
是接口,不同的实现类intercept方法做不一样的事情,但是最终都会调用传进去的next的proceed方法,而这个next就是RealInterceptorChain的对象。然后又new了一个自己,用来调用下一个处理者。

仿照OkHttp的责任链设计模式

责任链各个节点的接口


public interface IBaseTask {

    /**
     * 参数一:任务节点是否是终止节点的标志位
     * 参数二:下一个任务节点
     * @param isTask
     */
    public void doRunAction(String endFlag, IBaseTask nextTask);

}

链的组装者,将链的每个节点联系到一起

public class ChainManager implements IBaseTask {

    private List<IBaseTask> iBaseTaskList = new ArrayList<>();

    public void addTask(IBaseTask iBaseTask) {
        iBaseTaskList.add(iBaseTask);
    }

    private int index = 0;

    @Override
    public void doRunAction(String endFlag, IBaseTask nextTask) {
        if (iBaseTaskList.isEmpty()) {
            // 抛出异常..
            return;
        }

        if (index == iBaseTaskList.size() || index > iBaseTaskList.size()) {
            return;
        }

        IBaseTask iBaseTaskResult = iBaseTaskList.get(index);

        index ++;
        iBaseTaskResult.doRunAction(endFlag, nextTask);


    }
}

之所以要实现IBaseTask 接口,是为了能直接传递到IBaseTask 接口的方法doRunAction中。

各个任务节点类

拦截器一

public class Task1 implements IBaseTask {

    @Override
    public void doRunAction(String endFlag, IBaseTask nextTask) { // iBaseTask == ChainManager
        System.out.println("拦截器 任务节点一 处理了...");
        if ("123".equals(endFlag)) {
            return;
        }
        // 继续执行下一个链条的任务节点  ChainManager.doRunAction("ok", ChainManager)
        // ChainManager.doRunAction
        nextTask.doRunAction(endFlag, nextTask);
        
    }
}


拦截器二


public class Task2 implements IBaseTask {
    @Override
    public void doRunAction(String endFlag, IBaseTask nextTask) {
        System.out.println("拦截器 任务节点二 处理了...");
        if ("end".equals(endFlag)) {
            return;
        }
        // 继续执行下一个链条的任务节点
        nextTask.doRunAction(endFlag, nextTask);

    }
}


拦截器三

public class Task3 implements IBaseTask {

    @Override
    public void doRunAction(String endFlag, IBaseTask nextTask) {
        System.out.println("拦截器 任务节点三 处理了...");
        if ("123".equals(endFlag)) {
            return;
        }
        // 继续执行下一个链条的任务节点
        nextTask.doRunAction(endFlag, nextTask);
    }
}

测试代码


public class Test {

    public static void main(String[] args) {

        ChainManager chainManager = new ChainManager();

        chainManager.addTask(new Task1());
        chainManager.addTask(new Task2());
        chainManager.addTask(new Task3());

        chainManager.doRunAction("end", chainManager);

    }

}

执行结果

拦截器 任务节点一 处理了...
拦截器 任务节点二 处理了...

Process finished with exit code 0

任务一和任务二执行了, 因为任务二的标志位和结束标志位一致,所以任务三并没有执行,而是在任务二的时候就结束了,链也就在这里断了,不再往下执行了。 上面说了ChainManager 也继承IBaseTask是为了能传递下去, 从上面代码不难看出,从始至终只有一个ChainManager对象,贯穿整条链路。因为每次doRunAction的时候,传递的next都是ChainManager这个对象,所以都会执行ChainManager的doRunAction方法,与OkHttp相比,没有每次proceed就new一次ChainManager对象。其它的都是类似的功能了。 只至于OkHttp这么多拦截器都做了什么事情,下回分解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值