Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

23种设计模式之——责任链模式(okhttp 拦截器)

$
0
0

前言

网络七层协议

在现实中的责任链模型之一就是网络连接.对与程序猿而言,七层或五层的网络连接模型是肯定知道的.
当一个网络请求发出时,需要经过应用层->传输层->网络层->连接层->物理层
收到响应后正好反过来,物理层->连接层->网络层->传输层->应用层
在请求经过各层时,由每层轮流处理.每层都可以对请求或响应进行处理.并可以中断链接,以自身为终点返回响应

古代的三从四德

中国古代对妇女制定了“三从四德”的道德规范,“三从”是指“未嫁从父、既嫁从夫、夫死从子”,
也就是说一个女性,在没有结婚的时候要听从于父亲,结了婚后听从于丈夫,丈夫死了还要听儿子的,举
个例子来说,一个女的要出去逛街,同样这样的一个请求,在她没有出嫁前她必须征得父亲的同意,出嫁
之后必须获得丈夫的许可,那丈夫死了怎么办?一般都是男的比女的死的早,还要问问儿子是否允许自己

这里写图片描述

Okhttp中的Intercepter

最近比较火的okhttp中也使用了责任链模式,在Okhttp中,Intercepter就是典型的责任链的实现.它可以设置任意数量的Intercepter来对网络请求及其响应做任何中间处理.比如设置缓存,Https的证书验证,统一对请求加密/防串改,打印自定义Log,过滤请求等.

有点类似递归调用,拦截器可以方便的添加和移除。

责任链模式定义

百度给出的定义
责任链模式是一种设计模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

Okhttp责任链使用详解

uml类图

这里写图片描述

在Okh置ttp中,Intercepter就是典型的责任链的实现.它可以设任意数量的Intercepter来对网络请求及其响应做任何中间处理.比如设置缓存,Https的证书验证,统一对请求加密/防串改,打印自定义Log,过滤请求等.

package okhttp3;

import java.io.IOException;

/**
 * Observes, modifies, and potentially short-circuits requests going out and the corresponding
 * responses coming back in. Typically interceptors add, remove, or transform headers on the request
 * or response.
 */
public interface Interceptor {
  Response intercept(Chain chain) throws IOException;
}

接口很简单,主要就是拿到Chain 进行处理然后返回Response,而Chain中有三个待实现的方法
 interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    Connection connection();
  }

一般调用顺序就是 拿到Request后 chain.request();进行操作,然后传递下去给下面的拦截器进行处理   chain.proceed(request),

public final class GzipInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request original = chain.request();
        if (original.body() == null || original.header("Content-Encoding") != null) {
            return chain.proceed(original);
        }
        // 启用gzip
        Request request = original.newBuilder()
                .header("Content-Encoding", "gzip")
                .method(original.method(), gzip(original.body()))
                .build();
        return chain.proceed(request);
    }

这里需要分析 chain.proceed(request) 方法是如何进行链式传递的

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
    Connection connection) throws IOException {
  if (index >= interceptors.size()) throw new AssertionError();

  calls++;

  // If we already have a stream, confirm that the incoming request will use it.
  if (this.httpCodec != null && !sameConnection(request.url())) {
    throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
        + " must retain the same host and port");
  }

  // If we already have a stream, confirm that this is the only call to chain.proceed().
  if (this.httpCodec != null && calls > 1) {
    throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
        + " must call proceed() exactly once");
  }

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

  // Confirm that the next interceptor made its required call to chain.proceed().
  if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
    throw new IllegalStateException("network interceptor " + interceptor
        + " must call proceed() exactly once");
  }

  // Confirm that the intercepted response isn't null.
  if (response == null) {
    throw new NullPointerException("interceptor " + interceptor + " returned null");
  }

  return response;
}

上面的程序都能看懂,类似调用递归,每次进行new RealInterceptorChain ( index +1),获取到后面的拦截去,调用相应的实现方法。依次处理完所有的拦截

责任链优点

责任链模式屏蔽了请求的处理过程,你发起一个请求到底是谁处理的,这个你不用关心,只要你把请
求抛给责任链的第一个处理者,最终会返回一个处理结果(当然也可以不做任何处理),作为请求者可以不
用知道到底是需要谁来处理的,这是责任链模式的核心

观察者模式也可以实现请求的传递,比如一个事件发生了,通知
了观察者,同时观察者又作为一个被观察者,通知了另外一个观察者,这也形成了一个事件广播链,这和
责任链是有区别的:
受众数量不同。观察者广播链式可以 1:N 的方式广播,而责任链则要求是的 1:1 的传递,必然有一个
且只有一个类完成请求的处理;
请求内容不同。观察者广播链中的信息可以在传播中改变,但是责任链中的请求是不可改变的;

响应式编程Rxjava是不是采用的这种观察者模式进行链式调用???

引用:

责任链模式及OkHttp中的实现
http://www.jianshu.com/p/8b9f45a79ee6?utm_source=itdadao&utm_medium=referral

作者:o279642707 发表于2017/2/15 19:41:09 原文链接
阅读:10 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>