OkHttp中的设计模式之一:Builder模式
OkHttp中的设计模式之一:Builder模式1. 什么是Builder模式2. OkHttp中的实例2.1 OkHttpClient的构建方式2.1 OkHttpClient中的Builder2.1.1 通过Builder构建一个OkHttpClient2.1.2 默认的Builder2.1.3 反构建Builder3. Builder插件1. 什么是Builder模式关于什么是builder
OkHttp中的设计模式之一:Builder模式
1. 什么是Builder模式
关于什么是builder模式,具体可以参考一下这篇文章。
Builder模式分为:经典builder模式和变种builder模式。而在Android项目中,一般使用的都是变种Builder模式,OkHttp中也例外。不管是OkHttpClient
还是Request
,都是通过变种Builder模式进行构建的。下面来我们来看一下OkHttp的源码,来感受一下Builder模式的应用。
2. OkHttp中的实例
OkHttp
中很多类都有用到Builder
模式,使用上都大同小异,所以下面就以OkHttpClient
为例子,来讲一下Builder
模式在OkHttp
中的应用。
2.1 OkHttpClient的构建方式
构建OkHttpClient
有两种方式:
//方式1
OkHttpClient client1 = new OkHttpClient();
//方式2
OkHttpClient client2 = new OkHttpClient.Builder()
.writeTimeout(1000, TimeUnit.MILLISECONDS)
.readTimeout(1000, TimeUnit.MILLISECONDS)
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
return null;
}
})
.build();
}
方式2很明显,一看就是通过Builder模式构建的。但是实际上,方式1内部也是通过调用了new Builder()
的方式通过构建了一个默认参数的OkHttpClient
:
public OkHttpClient() {
this(new Builder());
}
2.2 OkHttpClient中的Builder
2.2.1 通过Builder构建一个OkHttpClient
OkHttpClient(Builder builder) {
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
this.protocols = builder.protocols;
this.connectionSpecs = builder.connectionSpecs;
this.interceptors = Util.immutableList(builder.interceptors);
this.eventListenerFactory = builder.eventListenerFactory;
if (builder.sslSocketFactory != null || !isTLS) {
this.sslSocketFactory = builder.sslSocketFactory;
this.certificateChainCleaner = builder.certificateChainCleaner;
} else {
X509TrustManager trustManager = Util.platformTrustManager();
this.sslSocketFactory = newSslSocketFactory(trustManager);
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
}
//还有一堆参数...
}
这个没啥好说的,就是将builder
中设置过的参数一一赋值给OkHttpClient
,然后可能还会做一些判断处理,保证参数的合法性。
2.2.2 默认的Builder
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
followRedirects = true;
retryOnConnectionFailure = true;
callTimeout = 0;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
//还有一堆参数...
}
在2.1 OkHttpClient
的构建方式中我们知道,OkHttpClient
的默认构造函数中就调用了Builder()
方式。在我们自己的项目中,也可以通过这种方式设置默认的参数,特别是一些必选项,防止因为调用者没有设置必选参数而出现问题。
OkHttpClient client1 = new OkHttpClient();
public OkHttpClient() {
this(new Builder());
}
2.2.3 反构建Builder
2.2.3.1 反构建的作用
public Builder newBuilder() {
return new Builder(this);
}
Builder(OkHttpClient okHttpClient) {
this.dispatcher = okHttpClient.dispatcher;
this.proxy = okHttpClient.proxy;
this.protocols = okHttpClient.protocols;
this.connectionSpecs = okHttpClient.connectionSpecs;
this.interceptors.addAll(okHttpClient.interceptors);
//还有一堆参数...
}
个人理解,反构建Builder
最主要的使用场景就是:当使用者构建了OkHttpClient
之后发现有一些参数需要改变,所以就可以通过反构建一个Builder
,然后调用Builder
的set方法修改对应的参数在build一次,生成新的OkHttpClient
对象。
当然,假如OkHttpClient
中有参数对应的set方法(实际上并没有),也是能修改参数的。但是这就违背了Builder
模式的设计原则,而且会引发一些问题:
1、比如我想重新设置
OkHttpClient
的sslSocketFactory
参数,使用Builder
模式时,在生成OkHttpClient
的时候是会做参数校验的(见2.1.1)。但是如果直接通过OkHttpClient
的set方法的形式,这个参数校验就会显得很麻烦,要在sslSocketFactory
和certificateChainCleaner
的set方法中都做一次校验。
2、这是我认为更关键的一个点:如果我们需要同时修改多个参数,并希望它们同时生效。在多线程高并发的情况下,很可能我们在获取参数配置的时候,只有部分参数是修改过的,还有部分参数是原来的值,这会引发很多不可预估的问题。
2.2.3.2 反构建的实际应用
在使用Interceptor
时,我们经常会使用到Request
的反构建,例如:
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//先走p2p请求,如果失败了,再走原始url请求。
Response response = chain.proceed(request.newBuilder().url(p2pUrl).build());
if (response.isSuccessful()) {
return response;
}
return chain.proceed(request);
}
3. Tips
3.1 Builder插件
手打Builder是一件非常痛苦的事情。不会偷懒的程序员不是好的程序员:),所以我们可以通过Builder插件来帮助我们自动化生成Builder。插件的名字叫做InnerBuilder。可以在File–>Settings–>Plugins中搜索"InnerBuilder"下载。
使用时,只需要在类的空白处按下快捷键Alt + Insert就可以看到Builder的选项。点击后,插件就会帮助我们自动化生成一个Builder了~
更多推荐
所有评论(0)