在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成。那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Builder模式来替代多参数构造函数是一个比较好的实践法则。
我们常常会面临编写一个这样的实现类(假设类名叫DoDoContact),这个类拥有多个构造函数,
DoDoContact(String name);
DoDoContact(String name, int age);
DoDoContact(String name, int age, String address);
DoDoContact(String name, int age, String address, int cardID);
这样一系列的构造函数主要目的就是为了提供更多的客户调用选择,以处理不同的构造请求。这种方法很常见,也很有效力,但是它的缺点也很多。类的作者不得不书写多种参数组合的构造函数,而且其中还需要设置默认参数值,这是一个需要细心而又枯燥的工作。其次,这样的构造函数灵活性也不高,而且在调用时你不得不提供一些没有意义的参数值,例如,DoDoContact("Ace", -1, "SH"),显然年龄为负数没有意义,但是你又不的不这样做,得以符合Java的规范。如果这样的代码发布后,后面的维护者就会很头痛,因为他根本不知道这个-1是什么含义。对于这样的情况,就非常适合使用Builder模式。Builder模式的要点就是通过一个代理来完成对象的构建过程。这个代理职责就是完成构建的各个步骤,同时它也是易扩展的。下面是改写自Effective Java里面的一段代码:
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
|
public class DoDoContact
{ private final int age; private final int safeID; private final String
name; private final String
address; public int getAge()
{ return age; } public int getSafeID()
{ return safeID; } public String
getName() { return name; } public String
getAddress() { return address; } public static class Builder
{ private int age
= 0 ; private int safeID
= 0 ; private String
name = null ; private String
address = null ; |
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
|
//
构建的步骤 public Builder(String
name) { this .name
= name; } public Builder
age( int val)
{ age
= val; return this ; } public Builder
safeID( int val)
{ safeID
= val; return this ; } public Builder
address(String val) { address
= val; return this ; } public DoDoContact
build() { //
构建,返回一个新对象 return new DoDoContact( this ); } } private DoDoContact(Builder
b) { age
= b.age; safeID
= b.safeID; name
= b.name; address
= b.address; } } |
最终,客户程序可以很灵活的去构建这个对象。
1
2
3
4
|
DoDoContact
ddc = new DoDoContact.Builder( "Ace" ).age( 10 ) .address( "beijing" ).build(); System.out.println( "name=" +
ddc.getName() + "age
=" +
ddc.getAge() +
"address" +
ddc.getAddress()); |