在我们生活中的对象比如汽车,它是由车轮、车架、发动机等组合起来的对象,但是往往使用的人只想要一辆汽车并不想知道创建汽车的过程此时就可以使用建造者模式。
在软件开发中,也存在大量类似汽车一样的复杂对象,它们拥有一系列成员属性,这些成员属性中有些是引用类型的成员对象。而且在这些复杂对象中,还可能存在一些限制条件,如某些属性没有赋值则复杂对象不能作为一个完整的产品使用;有些属性的赋值必须按照某个顺序,一个属性没有赋值之前,另一个属性可能无法赋值等。
复杂对象相当于一辆有待建造的汽车,而对象的属性相当于汽车的部件,建造产品的过程就相当于组合部件的过程。由于组合部件的过程很复杂,因此,这些部件的组合过程往往被“外部化”到一个称作建造者的对象里,建造者返还给客户端的是一个已经建造完毕的完整产品对象,而用户无须关心该对象所包含的属性以及它们的组装方式,这就是建造者模式的模式动机。
建造者模式是一个将复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示,属于创建型模式,使用建造者模式对于用户而言只需要指定需要建造的类型就可以获取对象,建造过程及细节不需要了解。
可以看一下传统建造者模式UML类图: 

其中主要的角色有四个:
举一个肯德基的套餐的例子。肯德基有很多套餐,肯德基的服务员需要根据用户的要求提供对应的的套餐。
@Data
@ToString
public class Combo {
private String title;
private String Hamburger;
private String chickenWings;
private String drumstick;
private String cola;
public Combo(String title){
this.title = title;
}
}
复制代码
public interface ComboBuilder {
Combo build();
void buildHamburger();
void buildChickenWings();
void buildDrumstick();
void buildCola();
}
复制代码
public class BComboBuilder implements ComboBuilder{
private final Combo mCombo = new Combo("B套餐");
@Override
public void buildHamburger() {
mCombo.setHamburger("两个套餐");
}
@Override
public void buildChickenWings() {
mCombo.setChickenWings("五个鸡翅");
}
@Override
public void buildDrumstick() {
mCombo.setDrumstick("三个鸡腿");
}
@Override
public void buildCola() {
mCombo.setCola("两个可乐");
}
public Combo build(){
return this.mCombo;
}
}
复制代码
public class AComboBuilder implements ComboBuilder {
private final Combo mCombo = new Combo("A套餐");
@Override
public void buildHamburger() {
mCombo.setHamburger("一个汉堡");
}
@Override
public void buildChickenWings() {
mCombo.setChickenWings("三个鸡翅");
}
@Override
public void buildDrumstick() {
mCombo.setDrumstick("三个鸡腿");
}
@Override
public void buildCola() {
mCombo.setCola("一个可乐");
}
public Combo build(){
return this.mCombo;
}
}
复制代码
public class Waiter {
private final ComboBuilder builder;
public Combo getCombo(){
return this.builder.build();
}
public Waiter(ComboBuilder builder){
this.builder = builder;
}
public void setBuilder() {
this.builder.buildChickenWings();
this.builder.buildCola();
this.builder.buildDrumstick();
this.builder.buildHamburger();
}
}
复制代码
public class Test {
public static void main(String[] args) {
AComboBuilder aComboBuilder = new AComboBuilder();
Waiter waiter = new Waiter(aComboBuilder);
waiter.setBuilder();
Combo combo = waiter.getCombo();
System.out.println(combo);
}
}
复制代码
public class AComboBuilder implements ComboBuilder {
private final Combo mCombo = new Combo("A套餐");
@Override
public ComboBuilder buildHamburger() {
mCombo.setHamburger("一个汉堡");
return this;
}
@Override
public ComboBuilder buildChickenWings() {
mCombo.setChickenWings("三个鸡翅");
return this;
}
@Override
public ComboBuilder buildDrumstick() {
mCombo.setDrumstick("三个鸡腿");
return this;
}
@Override
public ComboBuilder buildCola() {
mCombo.setCola("一个可乐");
return this;
}
public Combo build(){
return this.mCombo;
}
}
复制代码
public class Test {
public static void main(String[] args) {
AComboBuilder aComboBuilder = new AComboBuilder();
Combo combo = aComboBuilder.buildChickenWings()
.buildCola()
.buildDrumstick()
.buildHamburger()
.build();
System.out.println(combo);
}
}
复制代码
如上图所示不需要再一个一个写一个一个赋值了直接链式编程就好,还有一点上述的写法弃用了Director,个人感觉没必要硬着头皮要套传统模式的写法,也是可以有一些变通,主要是要适合自己的项目,如果就是一个对象的创建很复杂我们也可以将builder内嵌到类中如下:
@Data
@ToString
public class Combo {
private String title;
private String Hamburger;
private String chickenWings;
private String drumstick;
private String cola;
public Combo(String title){
this.title = title;
}
public static class Builder {
private final Combo mCombo = new Combo("A套餐");
public Builder buildHamburger() {
mCombo.setHamburger("一个汉堡");
return this;
}
public Builder buildChickenWings() {
mCombo.setChickenWings("三个鸡翅");
return this;
}
public Builder buildDrumstick() {
mCombo.setDrumstick("三个鸡腿");
return this;
}
public Builder buildCola() {
mCombo.setCola("一个可乐");
return this;
}
public Combo build(){
return this.mCombo;
}
}
}
复制代码
Combo combo = new Combo.Builder()
.buildChickenWings()
.buildCola()
.buildDrumstick()
.buildHamburger()
.build();
System.out.println(combo);
复制代码
根据自己的项目需求随机变通
这里就举 StringBuilder的例子吧 



这种情况就很适用建造者模式应为在拼接字符串中为了提高性能需要做很多处理,如果放在外面每次使用都要调用那么多代码很不方便
优点:
缺点: