在看okhttp源码的时候,发现了责任链模式。
所以今天复习一下这个模式。
使用责任链之前需要明确目的是什么, 按固定的步骤顺序,依次执行,它是一个业务的抽象模板。步骤可以很方便的增加减少。
以下用拦截器来表述每一个步骤。
责任链模式可以在拦截者的执行前后都可以拦截一次。 也就是上面说的增加步骤。
okhttp的责任链模式是靠一根总链条串联。而传统的链表式责任链是靠拦截者们自身串联的,通过事先set next.
以下是okhttp的责任链模式。这是简化后的责任链模式拦截器接口和链条类(管理类),
//拦截类需要实现的接口,
public interface Interceptor {
//处理完拦截后,调用chain.proceed(),等到所有的拦截器执行完回来。
//intercept的返回对象Response,是整个责任链模式最终处理的结果。
Response intercept(Chain chain);
// Chain 是串联起拦截器流程的链条。后面都是通过调用其proceed(Request request)串联起所有拦截器的。
interface Chain {
//链条类RealInterceptorChain实现这个接口,让各个拦截类内部处理完执行前的拦截后调用。
Response proceed(Request request);//request是给拦截器类的参数。各个拦截器可以利用request,也可以为下个拦截者预先处理一下。它的传递是通过在Chain接口定义方法实现。
//这里还可以定义一些方法,以从链条类RealInterceptorChain获取参数。
}
}
拦截器管理类。也就是链条类。
public final class RealInterceptorChain implements Interceptor.Chain {
private final List<Interceptor> interceptors;
private final int index;
//接下来定义的一些成员变量, 如果需要在拦截器里使用。必须要在interface Chain 定义一个get方法。
private Request request;
....
public RealInterceptorChain(List<Interceptor> interceptors, int index) {
this.interceptors = interceptors;
this.index = index;
}
public Response proceed() throws IOException {
// Call the next interceptor in the chain. 这是比较特别的, 每个拦截器执行前都要new一个管理类RealInterceptorChain
RealInterceptorChain next = new RealInterceptorChain(interceptors, , index + 1);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
return response;
}
}
拦截器的实现类之一
public final class BridgeInterceptor implements Interceptor {
private final CookieJar cookieJar;
public BridgeInterceptor(CookieJar cookieJar) {
this.cookieJar = cookieJar;
}
@Override public Response intercept(Chain chain) throws IOException {
T t = chain.getXXXXX(); //从管理类获取参数,
//第一次拦截, 也就是被拦截的还没执行之前。是马上可以被执行的。
Response networkResponse = chain.proceed(requestBuilder.build());
、
//第二次拦截。最终被拦截已经执行完毕。 所以不会马上执行, 因为递归完chain.proceed后,才到这里。
return responseBuilder.build();
}
}
public static void main(String[] args) {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
interceptors.add(new CallServerInterceptor(forWebSocket));// 最后面的是真实被拦截的。所以必须放最后,因为前面的拦截器都需要它执行完以后才返回。而且是不调用proceed(Chain chain)的
Interceptor.Chain chain = new RealInterceptorChain(interceptors, 0);
T result = chain.proceed(originalRequest);
}
总的感觉下来比较变扭。有两点:
1. 拦截者也变身为被拦截者。
2. 每次都new一个链条类。这是不符合设计初衷的,本身是链条,搞的却像个链接点. 而且calls的使用本来就已经和index重合