建造者(Builder)模式又是为了方便构造参数,采用链式调用可以更方便地填充对象参数。

首先我们先了解一下链式调用。

链式调用的本质是使调用方法返回下一个需要操作的对象,从而将数个方法通过一条语句的方式执行完毕。

我们比较常接触的链式调用就有StringBuilder,就像这样:

1
2
3
4
StringBuilder stb = new StringBuilder()
.append("123")
.append("321")
.append("1234567");

StringBuilder一样,很多的Builder也是采用了链式调用的方式让开发者使用。那么为什么建造者模式适合用链式调用风格呢?

我们先来看看什么是建造者模式。

建造者模式

建造者模式是一种设计模式,它描述了一个对象的创建过程。与直接new Object()不同,我们不直接将这个对象new出来,而是先创建一个它的建造者Builder,再通过Builder来创建这个对象。

例如OkHttp3中创建一个客户端对象:

1
2
3
4
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new CacheInterceptor(new Cache(new File("cache"), 20000)))
.build();

你可能就要问了,为什么不直接new OkHttpClient()呢,还要绕一圈用另外的对象来创建我们需要的对象?

首先,每个对象的建造者的目的都可能不一样,原因可能有这些:

  • 参数过多,使用set方式代码太多不够简洁
  • 存在set的内部逻辑,为了保持目标类set的纯净性,使用了建造者代理的方式
  • 屏蔽目标类的参数限制,比如过多的final参数使得直接构造目标类不方便
  • 延迟构建,降低不必要的性能消耗

所以建造者模式实际上就是辅助我们构建对象的工具,而链式调用就可以很直观地看出我们的建造过程,方便书写和理解。

举例

比如我们的建造者可以是这样的:

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
public class User {

private String name;

private String id;

/* Getter&Setter */

public static final class Builder {

private final User user;

public Builder() {
this.user = new User();
}

public Builder name(String name) {
user.setName(name);
return this;
}

public Builder id(String id) {
user.setId(id);
return this;
}

public User build() {
return user;
}
}
}

这里我们使用的就是内部静态类的方式,将每一个参数都进行了代理,这样我们就可以用下面这种方式来生成User对象了:

1
User user = new User.Builder().id("123").name("小明").build();

此时你会发现另一个问题,我们写了这么长一串,为什么不直接用更简洁的构造参数new User("123", "小明")呢?

因为正常情况下,在参数较少时我们并不会用建造者模式,一般只有在构造对象复杂的情况下才会用到建造者。

总结

建造者模式只是为了方便创建对象,实际上对于简单的POJO对象,我们甚至可以直接用建造者风格的set方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class User {

private String name;

private String id;

public String getName() {
return name;
}

public User setName(String name) {
this.name = name;
return this;
}

public String getId() {
return id;
}

public User setId(String id) {
this.id = id;
return this;
}
}

设计模式只是经过时间和代码量证明了的编程经验,但并不是真理。随着时代发展,设计模式也会不断地演化更替,只有适合自己(或是需求)的才是最好的。


本站总访问量