参考文章:https://howtodoinjava.com/design-patterns/creational/builder-pattern-in-java/
1、定义
Builder模式旨在“将复杂对象的构造与其表示分开,以便相同的构造过程可以创建不同的对象“。
2、什么情况下使用
我们已经知道应用程序中不可变性和不可变实例的好处。如果您对此有任何疑问,在java中String类。正如我已经说过的,构建器模式帮助我们创建具有大量状态属性的不可变类。
在任何用户管理模块中,主要实体是User,比方说。理想情况下,一旦用户对象完全创建,您就不希望改变它的状态。现在,让我们假设,我们的User对象具有以下5个属性,即firstName,lastName,age,phone和address。在通常的实践中,如果要创建不可变的User类,则必须将所有五个信息作为参数传递给构造函数。它看起来像这样:
1
2
3
4
5
6
7public User (String firstName, String lastName, int age, String phone, String address){
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.phone = phone;
this.address = address;
}现在firstName和lastName是必须的,其他三个属性是可选的,那么问题是,我们必须创建很多构造方法
1
2
3
4public User (String firstName, String lastName, int age, String phone){ ... }
public User (String firstName, String lastName, String phone, String address){ ... }
public User (String firstName, String lastName, int age){ ... }
public User (String firstName, String lastName){ ... }我们想上面这样写,现在我们需要添加第6个属性,我们可能需要创建更多的构造器,或者我们将对象变为可变并添加set方法,选择这种方法你将失去对象不可变。
构建模式可以帮助我们创建不可变的对象同时自定义添加属性。
3、构建模式的实现
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75public class User
{
//All final attributes
private final String firstName; // required
private final String lastName; // required
private final int age; // optional
private final String phone; // optional
private final String address; // optional
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
//All getter, and NO setter to provde immutability
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public String getPhone() {
return phone;
}
public String getAddress() {
return address;
}
public String toString() {
return "User: "+this.firstName+", "+this.lastName+", "+this.age+", "+this.phone+", "+this.address;
}
public static class UserBuilder
{
private final String firstName;
private final String lastName;
private int age;
private String phone;
private String address;
public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public UserBuilder address(String address) {
this.address = address;
return this;
}
//Return the finally consrcuted User object
public User build() {
User user = new User(this);
validateUserObject(user);
return user;
}
private void validateUserObject(User user) {
//Do some basic validations to check
//if user object does not break any assumption of system
}
}
}
1 | public static void main(String[] args) { |
4、jdk中的实现
java.lang.Appendable是构建模式实现的比较好的例子。
java.lang.StringBuilder#append() [线程不同步]
Java.lang.StringBuffer#append() [线程同步的]
java.nio.ByteBuffer#put() (also on CharBuffer, ShortBuffer, IntBuffer, LongBuffer, FloatBuffer and DoubleBuffer)
5、构建模式的好处
毫无疑问,在构建器模式中,代码行的数量至少增加了一倍,但是在设计灵活性和更易读的代码方面,这些努力得到了回报。减少了构造函数的参数,并以高度可读的方法调用提供。
Builder模式还有助于最小化构造函数中的参数数量,因此无需将可选参数的null传递给构造函数。
另一个优点是Object始终以完整状态实例化,而不是处于不完整状态。
最后,我可以在对象构建过程中构建不可变对象,而不需要太复杂的逻辑。
6、构建模式的缺点
虽然Builder模式减少了一些代码行,但不需要setter方法,但是通过引入Builder对象仍然可以使总行数增加一倍。此外,尽管客户端代码更具可读性,但客户端代码也更加冗长。