在看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重合


 


 

更多推荐