Builder模式

摘要:日常写代码有时候会遇到bean有很多的参数,也即是有多个构造器参数,这个时候我们可以考虑使用构建器。它既能保证像重叠构造器模式那样的安全性,也能保证像JavaBean模式那么好的可读性。这就是Builder模式。

正文:

讲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
38
39
40
41
42
43
44
45
46
package com.bean.builder;

public class Bean {
private int a;
private int b;
private int c;
private int d;
private int e;
private int f;
public Bean(int a, int b, int c, int d, int e, int f) {
super();
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
this.f = f;
}

public Bean(int a, int b, int c, int d, int e) {
super();
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
}



public Bean(int a, int b, int c, int d) {
super();
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}

// ....构造方法

public Bean() {
super();
}

//省略setter getter方法
}

由此可见,若想要灵活的new一个对象需要创建很多个重载的构造器,可读性和可维护性都不是很高。

使用构建器示例:

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
package com.bean.builder;

public class BuilderBean {
private final int a;
private final int b;
private final int c;
private final int d;
private final int e;
private final int f;

public static class Builder{
private final int a;
private final int b;

private int c = 0;
private int d = 0;
private int e = 0;
private int f = 0;

public Builder(int a,int b){
this.a = a;
this.b = b;
}

public Builder c(int val){
c = val;
return this;
}
public Builder d(int val){
d = val;
return this;
}
public Builder e(int val){
e = val;
return this;
}
public Builder f(int val){
f = val;
return this;
}

public BuilderBean build(){
return new BuilderBean(this);
}
}

private BuilderBean(Builder builder){
a = builder.a;
b = builder.b;
c = builder.c;
d = builder.d;
e = builder.e;
f = builder.f;
}

}

注意BuilderBean是不可变的,所有的默认参数值都单独放一个地方。builder的setter方法返回builder本身,以便后续继续调用别的方法。下面是客户端的代码

1
2
BuilderBean bb = new BuilderBean.Builder(10, 20).
c(3).e(5).f(6).build();

这样的客户端代码很容易编写,更重要的是易于阅读。与构造器相比,builder的微略优势在于,builder可以有多个可变的参数,构造器就像方法一样,只能有一个可变参数。

Builder模式的优点:

1.使用Builder模式必然会导致写两遍相关属性的代码和setter方法,看起来有点吃力不讨好。然而需要看到的是,客户端代码的可用性和可读性得到了大大提高。与此同时,构造函数的参数数量明显减少调用起来非常直观。

2.Builder模式十分灵活,可以利用单个builder构建多个对象,还可在创建期间进行调整根据对象的不同进行改变。

Builder模式的缺点:

1.为了创建对象,必须先创建它的构建器。虽然创建器的开销在实践中可能不那么明显,但是在某些十分注重性能的情况下,可能就成问题了。

2.Builder模式还比重叠构造器模式更加冗长,最好在4个或4个以上的参数才使用。

在我的Builder实现中,我会用Builder的构造函数而不是set方法传递客户需要的属性。这样做的好处在于,对象总是能被一次完整的实例化,而不是靠开发人员调用时用set方法补充额外的属性完成实例化。这也体现了不可变性带来的好处。然而,相应地也会造成自己设定的属性方法可读性降低。

总结:
如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder是种不错的选择,特别是当大多数参数都是可选的时候。与使用传统的重叠构造器模式相比,使用Builder模式的客户端代码更易于编写和阅读,构建器也比JavaBean更加安全。