何为builder模式
当我们通过构造方法来创建一个类时,往往需要传入一些列参数,这本无可厚非,但如果这个类的构造参数较多,并且涉及到稍复杂的业务,而这些业务逻辑是由构造方法传入的参数按照一定的逻辑搭建起来的,这个时候我们如果直接通过构造函数来获取对象的话,就很难了解这一些列参数的意义了。因此,通过内部类Build来管理这一系列参数,并且由它来生成类对象。
实例代码如下:
public class Person {
private String mouse;
private String eye;
private String ear;
private String teath;
public Person(String mouse, String eye, String ear, String teath) {
super();
this.mouse = mouse;
this.eye = eye;
this.ear = ear;
this.teath = teath;
}
public String mouse(){
return mouse;
}
public String eye(){
return eye;
}
public String ear(){
return ear;
}
public String teath(){
return teath;
}
public void show(){
System.out.println("人的面部组成:"+mouse+" "+eye+" "+ear+" "+teath);
}
public static final class Build{
private String mouse;
private String eye;
private String ear;
private String teath;
public Build(){
}
public Build mouse(String mouse){
this.mouse = mouse;
return this;
}
public Build eye(String eye){
this.eye = eye;
return this;
}
public Build ear(String ear){
this.ear = ear;
return this;
}
public Build teath(String teath){
this.teath = teath;
return this;
}
public Person build(){
return new Person(mouse,eye,ear,teath);
}
}
}
public static void main(String[] args){
Person p = new Person.Build()
.mouse("嘴巴")
.eye("眼睛")
.ear("耳朵")
.teath("牙齿")
.build();
p.show();
}
如上,构建Person对象时需要传入4个参数,按照普通方法我们直接通过构造函来创建,这样会显得很臃肿,并且不知道这些参数的意义。
在android开发中,我们经常会用到一些开源的网络加载框架,比如Retrofit.
public final class Retrofit {
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
private final okhttp3.Call.Factory callFactory;
private final HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories;
private final List<CallAdapter.Factory> adapterFactories;
private final Executor callbackExecutor;
private final boolean validateEagerly;
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
public okhttp3.Call.Factory callFactory() {
return callFactory;
}
/** The API base URL. */
public HttpUrl baseUrl() {
return baseUrl;
}
public List<CallAdapter.Factory> callAdapterFactories() {
return adapterFactories;
}
public List<Converter.Factory> converterFactories() {
return converterFactories;
}
public Executor callbackExecutor() {
return callbackExecutor;
}
public static final class Builder {
private Platform platform;
private okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private List<Converter.Factory> converterFactories = new ArrayList<>();
private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
private Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
}
public Builder() {
this(Platform.get());
}
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;
}
/** Add converter factory for serialization and deserialization of objects. */
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
/**
* Add a call adapter factory for supporting service method return types other than {@link
* Call}.
*/
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
public Builder callbackExecutor(Executor executor) {
this.callbackExecutor = checkNotNull(executor, "executor == null");
return this;
}
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}
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();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
}
}
上面是精简后的Retrofit.java类,可以看到要创建一个Retrofit对象,需要的参数很多,而这些参数有对应着一些列业务,因此通过构建这模式来创建,我们可以根据构建名称来知道这些参数的意思,并且构建逻辑,业务顺序也更加清晰。
好了,关于构建者模式就介绍到这儿了。