设计模式之建造者模式(Builder Pattern)
前言
当一个类的参数多的情况下,使用重叠构造器模式客户端代码会很难编写,并且可读性差;使用javabean模式,调用一个无参的构造器,然后调用setter方法来设置每个必要的参数。但是javabean自身有着严重的缺点,因为构造过程被分到几个调用中,在构造javabean可能处于不一致的状态,类无法仅仅通过检验构造器参数的有效性来保证一致性。另一点不足之处,javabean模式阻止了把类做成不可变的可能,这就需要程序员付出额外的努力来确保他的线程安全; build模式 既能保证像重叠构造器那样的安全,也能实现JavaBean模式那样的可读性。
使用build模式的步骤:
- 不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个build对象。
- 然后让客户端在build对象上调用类似的setter方法来设置每个相关的可选参数,
- 最后,客户端调用无参的build方法来生成不可变的对象。这个builder是它构建的静态成员类。
Builder模式
编写对象类
1 | public class Person{ |
调用
1 | public static void main(String[] args){ |
输出:1
Person{id=1, name='张三', age=18, sex='男', phone='null', address='null', desc='测试使用builder模式'}
返厂重造
当使用builder构造了一个对象时,如果后期需要对该对象进行属性的修改或者设置其他未设置的属性,可以使用如下方法:
- 在Builder类中增加构造方法
1
2
3
4
5
6
7
8
9public Builder(Person person) {
this.id = person.id;
this.name = person.name;
this.age = person.age;
this.sex = person.sex;
this.phone = person.phone;
this.address = person.address;
this.desc = person.desc;
}
可以发现,这里与Person对象的构造函数是对称的
在Person类中增加方法
1
2
3public Builder newBuilder() {
return new Builder(this);
}调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public static void main(String[] args) {
Person personA = new Person.Builder(1, "张三")
.age(18)
.sex("男")
.desc("测试使用builder模式")
.build();
Person newPerson = personA.newBuilder()
.address("new address")
.desc("测试使用builder模式更改对象属性")
.build();
System.out.println(personA.toString());
System.out.println(newPerson.toString());
}
输出1
2Person{id=1, name='张三', age=18, sex='男', phone='null', address='null', desc='测试使用builder模式'}
Person{id=1, name='张三', age=18, sex='男', phone='null', address='new address', desc='测试使用builder模式更改对象属性'}
注意:这里personA和newPerson是两个不同的对象了
Builder模式在Java中的实例
- StringBuilder.append();
Guava Cache
1
2
3
4
5
6
7
8
9
10LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.removalListener(MY_LISTENER)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});android中okHttp、AlertDialog均有广泛使用
总结
- 在要构建的类内部创建一个静态内部类 Builder
- 静态内部类的参数与构建类一致
- 构建类的构造参数是 静态内部类,使用静态内部类的变量一一赋值给构建类
- 静态内部类提供参数的 setter 方法,并且返回值是当前 Builder 对象,从而实现链式调用
- 最终提供一个 build 方法构建一个构建类的对象,参数是当前 Builder 对象
- 返厂重造需求
- lombok的@Data等参数提供了自动生成getter、setter、构造函数、toString()等方法,结合实际情况结合使用
Read More
[1] Java高效编程之Builder模式
[2] 变种 Builder 模式:优雅的对象构建方式
[3] 设计模式 Build 模式
[4] Java Builder 模式,你搞懂了么?