盘点android中常见的设计模式(五) -- 责任链模式

简介:

依赖倒转原则

今天来说一下设计模式的6大原则之一的依赖倒转原则。这个原则是开闭原则的基础,其具体的内容为:针对接口编程,依赖于抽象而不依赖于具体。

 

责任链模式:

责任链模式(Chain of Responsibility Pattern)为请求创建一个接收者对象的链,这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依次类推,直到该请求被处理。

该设计模式主要有以下几个优点:

  1. 降低耦合度
  2. 简化了对象
  3. 增加了对象指派职责的灵活性
  4. 方便增加新的请求处理类

 

Android中的使用:

责任链模式在android中的运用场景有很多,先说说我们常见的事件传递,事件分发机制,它就是一种典型的责任链模式。众所周知事件的传递顺序是:Acitivity -> Window -> DecorView -> ViewGroup -> View。当一个点击事件发送后,首先是手机硬件传感器传递给Activity,然后在通过Window传递给DecorView,最终传递到View,那么这整个传递和事件处理的过程就是一种责任链。关于android的事件分发机制这里不再赘述,感兴趣的可以自行了解。

责任链模式在一些很流行的框架中也有被应用,比如我们熟悉的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);
  }

这段代码我们可以看到首先创建一个集合用来存放拦截器(这些拦截器就是责任链中的请求的接收者)。这些拦截器都实现了同一个接口和接口中的通用方法。

public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    /**
     * Returns the connection the request will be executed on. This is only available in the chains
     * of network interceptors; for application interceptors this is always null.
     */
    @Nullable Connection connection();

    Call call();

    int connectTimeoutMillis();

    Chain withConnectTimeout(int timeout, TimeUnit unit);

    int readTimeoutMillis();

    Chain withReadTimeout(int timeout, TimeUnit unit);

    int writeTimeoutMillis();

    Chain withWriteTimeout(int timeout, TimeUnit unit);
  }
}

可以看到Interceptor接口中的抽象方法intercept即为需要实现的通用方法,它返回的是一个经过当前拦截器处理之后的Response。我们回到主线,可以看到核心代码的最后创建了RealInterceptorChain责任链,并将拦截器的集合作为参数传递给了该对象,最后调用proceed方法开始执行该责任链。

 /**
   * 简化后的代码
   */
 public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec         
  httpCodec,
      RealConnection connection) throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

    calls++;

    ......

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

    ......

    return response;
  }

以上是简化后的proceed方法,其核心代码就三句,创建一个新的责任链(该责任链的初始下标为index+1),从集合中获取拦截器(接收者),调用拦截器的intercept方法。这里我们以BridgeInterceptor为例,看看具体的实现代码。

@Override public Response intercept(Chain chain) throws IOException {
    Request userRequest = chain.request();
    Request.Builder requestBuilder = userRequest.newBuilder();

    ......     

    Response networkResponse = chain.proceed(requestBuilder.build());

    ......    

    return responseBuilder.build();
  }

这里我们省略了该拦截器对请求的处理内容,可以看到最终又执行到了proced方法。到这里我们其实已经知道了OkHttp的获取请求结果的思想就是不断的创建越来越短的责任链去执行拦截器中的处理请求的方法从而获得最终的我们所需要的返回结果。

发布了10 篇原创文章 · 获赞 3 · 访问量 495

猜你喜欢

转载自blog.csdn.net/ledding/article/details/104693065
今日推荐