构建型设计模式--建造者模式

建造者模式 Builder

建造者模式用于创建过程稳定,但配置多变的对象。在《设计模式》一书中的定义是:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

经典的“建造者-指挥者”模式现在已经不太常用了,现在建造者模式主要用来通过链式调用生成不同的配置。比如我们要制作一杯珍珠奶茶。它的制作过程是稳定的,除了必须要知道奶茶的种类和规格外,是否加珍珠和是否加冰是可选的。使用建造者模式表示如下:

public class MilkTea {
private final String type;
private final String size;
private final boolean pearl;
private final boolean ice;

private MilkTea() {}

private MilkTea(Builder builder) {
this.type = builder.type;
this.size = builder.size;
this.pearl = builder.pearl;
this.ice = builder.ice;
}

public String getType() {
return type;
}

public String getSize() {
return size;
}

public boolean isPearl() {
return pearl;
}
public boolean isIce() {
return ice;
}

public static class Builder {

private final String type;
private String size = "中杯";
private boolean pearl = true;
private boolean ice = false;

public Builder(String type) {
this.type = type;
}

public Builder size(String size) {
this.size = size;
return this;
}

public Builder pearl(boolean pearl) {
this.pearl = pearl;
return this;
}

public Builder ice(boolean cold) {
this.ice = cold;
return this;
}

public MilkTea build() {
return new MilkTea(this);
}
}
}

可以看到,我们将 MilkTea 的构造方法设置为私有的,所以外部不能通过 new 构建出 MilkTea 实例,只能通过 Builder 构建。对于必须配置的属性,通过 Builder 的构造方法传入,可选的属性通过 Builder 的链式调用方法传入,如果不配置,将使用默认配置,也就是中杯、加珍珠、不加冰。根据不同的配置可以制作出不同的奶茶:


public class User {
private void buyMilkTea() {
MilkTea milkTea = new MilkTea.Builder("原味").build();
show(milkTea);

MilkTea chocolate =new MilkTea.Builder("巧克力味")
.ice(false)
.build();
show(chocolate);

MilkTea strawberry = new MilkTea.Builder("草莓味")
.size("大杯")
.pearl(false)
.ice(true)
.build();
show(strawberry);
}

private void show(MilkTea milkTea) {
String pearl;
if (milkTea.isPearl())
pearl = "加珍珠";
else
pearl = "不加珍珠";
String ice;
if (milkTea.isIce()) {
ice = "加冰";
} else {
ice = "不加冰";
}
System.out.println("一份" + milkTea.getSize() + "、"
+ pearl + "、"
+ ice + "的"
+ milkTea.getType() + "奶茶");
}
}

好处

使用建造者模式的好处是不用担心忘了指定某个配置,保证了构建过程是稳定的。在 OkHttp、Retrofit 等著名框架的源码中都使用到了建造者模式。

总结

构造者实际为配置类,是一个静态内部类。用来作为目标类的的构造方法的入参。构造者 在build方法中new 出目标类,其它方法中则设置属性返回this(构造者)以形成配置的链式调用。