设计模式(五)OkHttp的责任链模式

5,278 阅读4分钟

一、基本概念

1、定义

多个对象都有机会处理请求,将这些对象连成一个链,将请求沿着这条链传递,直到有对象处理为止。

2、使用场景

  • 多个对象处理同一请求,具体哪个对象处理需要动态决定
  • 需要指定一组对象处理请求

3、优点

  • 将处理者和请求者进行解耦

4、缺点

  • 需要对处理者进行遍历,处理者过多会影响性能

5、类图

  • Handler:抽象处理者,声明请求处理的方法,并保持对下一个处理节点Handler的引用
  • ConcreteHandler:具体处理者,对请求进行处理,如果不能处理将请求转发给下一个节点

二、实例

1、抽象类Handler

/**
 * @Description 抽象处理者
 */
public abstract class Handler {
  //下一个处理者
  private Handler mNextHandler;

  public Handler(){

  }

  /**
   * 传入下一个处理者
   * @param nextHandler
   */
  public Handler(Handler nextHandler) {
    this.mNextHandler = nextHandler;
  }

  /**
   * 处理请求
   */
  public final void handleRequest(Request request) {
    //请求者和处理者级别相同才进行处理
    if (getCurLevel() == request.getRequestLevel()) {
      handle(request);
    } else {
      //否则将请求交给下一个处理者
      if (mNextHandler != null) {
        mNextHandler.handleRequest(request);
      } else {
        System.out.print("无人处理");
      }
    }
  }

  /**
   * 获取处理者的级别
   * @return
   */
  protected abstract int getCurLevel();

  /**
   * 当前处理者处理的逻辑
   * @param request
   */
  protected abstract void handle(Request request);

}

2、具体处理者

public class HandlerA extends Handler {
  public HandlerA(Handler nextHandler) {
    super(nextHandler);
  }

  @Override
  protected int getCurLevel() {
    return 6;
  }

  @Override
  protected void handle(Request request) {
    System.out.print("HandlerA 进行处理");
  }
}
public class HandlerB extends Handler {
  public HandlerB() {
    
  }

  public HandlerB(Handler nextHandler) {
    super(nextHandler);
  }

  @Override
  protected int getCurLevel() {
    return 10;
  }

  @Override
  protected void handle(Request request) {
    System.out.print("HandlerB 进行处理");
  }
}

3、抽象请求

public abstract class Request {
  /**
   * @return 请求的级别
   */
  public abstract int getRequestLevel();
}

4、具体请求

public class RequestA extends Request {
  @Override
  public int getRequestLevel() {
    return 10;
  }
}

5、使用

public class HandlerTest {
  public static void main(String[] args) {
    RequestA request = new RequestA();
    //最后一个处理者
    Handler handlerB  = new HandlerB();
    //第一个处理者
    Handler handlerA = new HandlerA(handlerB);
    //最终传递到HandlerB处理
    handlerA.handleRequest(request);
  }
}

三、OkHttp的Interceptor

纯的责任链模式是如果被处理者进行处理了,则请求传递结束。OkHttp的拦截器是不纯的责任链模式,在请求到达时,拦截器会做一些处理(比如添加参数等),然后传递给下一个拦截器进行处理。

1、请求拦截处理

在请求过程中,通过拦截器对请求进行处理

Response response = getResponseWithInterceptorChain();
Response getResponseWithInterceptorChain() throws IOException {
    // 创建拦截器的list
    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));
    // 创建RealInterceptorChain,传入的index索引为0
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
}

创建首个RealInterceptorChain对象,并传入拦截器的集合,通过proceed进行请求的处理。

2、请求处理

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
    RealConnection connection) throws IOException {
  ......
  // 创建下一个RealInterceptorChain,将index+1(下一个拦截器索引)传入
  RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
      connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
      writeTimeout);
  //获取当前的拦截器
  Interceptor interceptor = interceptors.get(index);
  //通过Interceptor的intercept进行处理
  Response response = interceptor.intercept(next);
  ......
  return response;
}
  • 创建下一个RealInterceptorChain对象,并将当前RealInterceptorChain中的变量当成参数传入,并将索引index+1传入。
  • 获取当前index位置上的拦截器,第一次创建时传入的index为0,表示获取第一个拦截器,后面会将index+1进入传入,用于获取下一个拦截器。
  • 在Interceptor的intercept中,将下一个RealInterceptorChain传入,内部会调用下一个RealInterceptorChain的proceed方法

3、Interceptor接口

public interface Interceptor {
  /**
   * 拦截Chain,并触发下一个拦截器的调用
   * @param chain 被处理的对象
   * @return
   * @throws IOException
   */
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    //返回请求
    Request request();
    //对请求进行处理
    Response proceed(Request request) throws IOException;
    ......
  }
}

4、ConnectInterceptor

public final class ConnectInterceptor implements Interceptor {
  public final OkHttpClient client;

  public ConnectInterceptor(OkHttpClient client) {
    this.client = client;
  }

  @Override public Response intercept(Chain chain) throws IOException {
    //下一个拦截链
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    //获取Request进行处理
    Request request = realChain.request();
    StreamAllocation streamAllocation = realChain.streamAllocation();

    // We need the network to satisfy this request. Possibly for validating a conditional GET.
    boolean doExtensiveHealthChecks = !request.method().equals("GET");
    HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
    RealConnection connection = streamAllocation.connection();
    //会调用下一个拦截链的proceed进行处理
    return realChain.proceed(request, streamAllocation, httpCodec, connection);
  }
}

ConnectInterceptor作为一个具体的处理者,接收到下一个RealInterceptorChain对象,通过RealInterceptorChain的proceed方法对请求进行处理。
整个链式调用的流程为:
首个Chain procced--首个Interceptor interceptor--
下一个Chain procced--下一个Interceptor interceptor--
下一个Chain procced--下一个Interceptor interceptor....

汇总:设计模式总结