Builder Pattern
创建者模式
定义
Builder design pattern is an alternative way to construct complex objects and should be used only when we want to build different types of immutable objects using same object building process.
特征
- 创建复杂对象构造方法的替代品
- 创建不可变对象
- 相同的创建过程
- 一步一步地,创建过程可控制的
和抽象工厂方法的区别
In one sentence, abstract factory pattern is the answer to "WHAT" and the builder pattern to "HOW".
fluent interface
A fluent interface is normally implemented by using method cascading (or method chaining).
创建者模式更像流式接口,方法链的模式
UML 类图

场景
构建一个不可变复杂对象,这样的构造方法很麻烦、容易出错;添加一个属性,使用构造方法的地方,都需要去修改。
public 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;
}
当然可以写多个构造方法,也比较复杂和麻烦
public 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){ ... }
样例
使用 Builder ,就很简单,容易扩展了。
public 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;
}
@Override
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
}
}
}
使用方法
public static void main(String[] args) {
User user1 = new User.UserBuilder("Lokesh", "Gupta")
.age(30)
.phone("1234567")
.address("Fake address 1234")
.build();
System.out.println(user1);
User user2 = new User.UserBuilder("Jack", "Reacher")
.age(40)
.phone("5655")
//no address
.build();
System.out.println(user2);
User user3 = new User.UserBuilder("Super", "Man")
//No age
//No phone
//no address
.build();
System.out.println(user3);
}
Output:
User: Lokesh, Gupta, 30, 1234567, Fake address 1234
User: Jack, Reacher, 40, 5655, null
User: Super, Man, 0, null, null
优势
- 代码可读性增强
- 减少构造方法个数
- 减少 Setter() 方法
劣势
- 代码行数增加
Existing implementations in JDK
All implementations of java.lang.Appendable are infact good example of use of Builder pattern in java. e.g.
java.lang.StringBuilder#append() [Unsynchronized class]
java.lang.StringBuffer#append() [Synchronized class]
java.nio.ByteBuffer#put() (also on CharBuffer, ShortBuffer, IntBuffer, LongBuffer, FloatBuffer and DoubleBuffer)
样例
StringBuilder builder = new StringBuilder("Temp");
String data = builder.append(1)
.append(true)
.append("friend")
.toString();
System.out.println(data);
Output:
Temp1truefriend
MyBatis 中的应用
- MyBatis 中的 CacheBuilder 构建二级缓存 Cache 对象时,使用了构建者模式