说明
在众多开源框架或者jdk源码中常常出现Builder,build相关的类文件名或者类名,函数名。其中很多如此命名的原因就是因为使用了建造者(Builder)模式。查看jdk源码不难发现,我们常用的StringBuilder类也使用了建造者模式。
建造者模式介绍摘要
- 定义: 将一个复杂对相当构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
- 特征. 用户只需指定需要建造的类型就可以得到它们,建造过程和细节不需要知道
- 类型:创建型
- 适用场景:如果一个对象有非常复杂的内部结构(很多属性);想把复杂对象的创建和使用分离。
- 优点:
- 封装性好
- 扩展性好,建造类之间独立,一定程度上解耦。
- 缺点:
- 产生多余的Builder对象
- 产品内部发生变化,建造者都要修改,成本较大
代码实现
场景:我们现在打算入驻网店,所以要提交一份申请资料,申请一个网店店铺。申请资料提交给业务员(Builder),业务员负责处理相关数据,并将网店的申请结果(Shop类)返回给申请者。
首先,我们要知道的是具体的建造过程是 由Builder对象完成的。外界直接通过Builder对象来建造获取一个Shop类的实例。具体的UML类图:

这里我们只使用一个Shop类,并且在Shop类中有个内部类。用于创建Shop实体类。我们先直接看外部测试代码,很容易理解:
public class Test {
public static void main(String[] args) {
// 按需,Build相应的属性覆盖默认的属性。
// build()接在buildXX()属性之后,直接能够返回相应的Shop对象实例。
Shop shop = new Shop.ShopBuilder()
.buildShopName("My Shop Name")
.buildShopDesc("WelCome to my Shop")
.buildShopPhone("13012345678")
.buildShopPhoto("http://xxx.com/i/img.jpg")
.build();
System.out.println(shop);
}
}
下面是Shop的具体实现类:
public class Shop {
private String name;
private String description;
private String phone;
private String photo;
// 在Builder类内部,通过 return new Shop(this)直接返回一个Shop对象。
public Shop(ShopBuilder shopBuilder){
this.name = shopBuilder.name;
this.description = shopBuilder.description;
this.phone = shopBuilder.phone;
this.photo = shopBuilder.photo;
}
//为了方便查看build结果,我们重写toString方法。
@Override
public String toString() {
return "Shop{" +
"name='" + this.name + '\'' +
", description='" + this.description + '\'' +
", phone='" + this.phone + '\'' +
", photo='" + this.photo + '\'' +
'}';
}
// 这里是Builder类,负责Build建造。
// 注意1:buildXX()属性,返回值为本身,这样方便链式操作。
// 注意2:最后的build()函数,直接build出我们最终想要的实体对象。
public static class ShopBuilder{
private String name = "Default name";
private String description = "Welcome to Default name 's Shop.";
private String phone = "Default number";
private String photo = "Default photo";
public ShopBuilder buildShopName(String name) {
this.name = name;
return this;
}
public ShopBuilder buildShopDesc(String desc) {
this.description = desc;
return this;
}
public ShopBuilder buildShopPhone(String phone) {
this.phone = phone;
return this;
}
public ShopBuilder buildShopPhoto(String photo) {
this.photo = photo;
return this;
}
public Shop build() {
return new Shop(this);
}
}
}