简介:
Builder 模式是一个创建复杂对象的创建模式,可以对用户隐藏复杂的内部构建细节,对外只提供用户关心的构建部件接口,降低构建过程和部件的耦合。
UML类图
我们可以看出,通常会设计一个抽象的构建类Builder,通常这个抽象类包含数个设置部件的抽象方法,然后设计不同产品的构建类ConcreteBuilder去继承他从而重写它的实现方法, 我们可以看出Builder类和ConcreteBuilder之间是泛化关系,并且通常会设计一个Direcotr类用来隐藏组装过程,这里我们也可以看出这里是聚合关系。
案例讲解
实现某种功能的代码可以又很多种不同的方式,只要达到我们所需要的效果就行,这里同学们不需要拘泥于上面的固定的UML图,按照模板去设计,用其它关系一样可以实现Builder模式,这里我们看看Retrofit这个开源框架是如何实现Builder模式的。
通过网络通信框架-Retrofit这篇我们可以看到,我们需要构建一个Retrofit类,通过这个类来创建一个接口对象,从而调用服务器接口,那么Retrofit是怎么使用构建模式的呢?首先我们知道Retrofit类可以配置很多东西,包括支持自定义客户端的配置,回调工厂的配置,json转化的配置,服务器url的配置等等,并且是由Retrofit的内部类Builder来负责的提供的,我们来看下这些方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public Builder client(OkHttpClient client) { return callFactory(checkNotNull(client, "client == null")); } public Builder callFactory(okhttp3.Call.Factory factory) { this.callFactory = checkNotNull(factory, "factory == null"); return this; } public Builder baseUrl(String baseUrl) { checkNotNull(baseUrl, "baseUrl == null"); HttpUrl httpUrl = HttpUrl.parse(baseUrl); if (httpUrl == null) { throw new IllegalArgumentException("Illegal URL: " + baseUrl); } return baseUrl(httpUrl); } public Builder baseUrl(HttpUrl baseUrl) { checkNotNull(baseUrl, "baseUrl == null"); List<String> pathSegments = baseUrl.pathSegments(); if (!"".equals(pathSegments.get(pathSegments.size() - 1))) { throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl); } this.baseUrl = baseUrl; return this; } public Builder addConverterFactory(Converter.Factory factory) { converterFactories.add(checkNotNull(factory, "factory == null")); return this; } public Builder addCallAdapterFactory(CallAdapter.Factory factory) { adapterFactories.add(checkNotNull(factory, "factory == null")); return this; }
|
从这里我们可以看出,大部分只是做了一个基础的校验,然后便赋值给内部的全局变量了,那么它的构建过程呢,我们看看Retrofit.Builder的build()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public Retrofit build() { if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories); return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); }
|
这里我们看到它通过Retrofit的构造方法将用户设置的部件传入从而构建出Retrofit对象,是不是发现这里的构建方式为什么没有UML图那么多类和复杂,这是因为这里的对象并没有那么复杂,只是构建了Retrofit这一种类型对象,这里的设计主要还是对用户屏蔽Retrofit内部构建细节,当碰到多种类型的构建产品对象时,我们可以进一步将Builder类提取出来成为抽象类,并抽象出公共方法,那么这样便像UML图设计中所示了。由于这里也不需要设计不同的控制流程,因此将UML中的Director类也省去了,以build()来返回自身进行链式调用,看上去也更简洁了,也减少了类开销。所以这里我们可以看出,在实际的开发需求中,不要过度设计,因为过度设计虽然在扩展上比较好,但是也带来了大量的没必要的类开销以及繁重的工作和使用难度。