一、什么是建造者
建造者模式适用于那些基本部件固定但组合方式经常变化的场景,例如馒头坊提供定制化服务,顾客可以选择大小、形状和馅料等属性,通过分步骤选择,建造者模式允许以不同的顺序和组合构建出个性化的馒头。同样,在烧烤穿串中,固定的食材如鸡肉、牛肉可以通过不同的穿制方式和组合,形成多样化的烧烤产品,如中国的鸡肉串和日本的烧鸟,建造者模式使得这些固定材料的不同组合变得灵活而高效。
二、为什么用建造者
-
封装部件(隔离复杂性、代码复用):
建造者模式隐藏了产品部件内部的复杂性,客户端只需与建造者接口交互,而不需要了解对象的具体构建细节。 -
实现独立,易扩展(灵活性、可定制性):
由于建造者的具体实现是独立的,新增或修改建造者不会影响其他部分。这使得添加新产品或改变现有产品的构建过程变得更加容易。 -
控制构建细节(清晰的构建步骤):
建造者模式允许开发者对构建过程进行逐步细化,每一步都可以精心设计,确保构建的正确性。这种逐步构建的方式降低了错误传播的风险,并且不对其他模块产生影响。
适用于什么场景:
- 复杂对象的构建:当对象的构建过程涉及多个步骤,或者对象由多个部分组成时。
- 相似对象的不同表示:需要创建一系列相似或相同但具有不同属性的对象时。
- 不可变对象:需要创建一旦构建完成就不可更改的对象时。
- 分步骤构建:构建过程需要分步骤进行,每一步可能依赖于前一步的结果。
- 多配置选项:对象的配置选项很多,且这些选项经常变化时。
三、建造者示例
场景描述
假设我们有一个馒头坊,提供定制化馒头服务。顾客可以根据自己的喜好选择馒头的不同属性,比如大小、形状、馅料等。馒头坊使用建造者模式来满足顾客的个性化需求(前提他要是的馒头)。
代码示例
来个制作馒头产品的模子,配件可定制,产品属性随意搭配。
// 产品:馒头
class Mantou {
private String size;
private String shape;
private Filling filling;
// 建造者模式的方法,设置馒头的各个属性
public void setSize(String size) {
this.size = size;
}
public void setShape(String shape) {
this.shape = shape;
}
public void setFilling(Filling filling) {
this.filling = filling;
}
public void display() {
System.out.println("Mantou - Size: " + size + ", Shape: " + shape + ", Filling: " + filling.getDescription());
}
}
可定制的组件:馅料
// 馅料接口
interface Filling {
String getDescription();
}
// 具体馅料实现
class RedBeanFilling implements Filling {
public String getDescription() {
return "Red Bean";
}
}
class MeatFilling implements Filling {
public String getDescription() {
return "Meat";
}
}
// 更多馅料实现...
馒头产品的构建者:制作馒头的师傅
// 抽象建造者
interface MantouBuilder {
void buildSize();
void buildShape();
void buildFilling(Filling filling);
Mantou getMantou();
}
// 具体建造者
class CustomMantouBuilder implements MantouBuilder {
private Mantou mantou = new Mantou();
public void buildSize() {
// 假设顾客选择了“大”馒头
mantou.setSize("Large");
}
public void buildShape() {
// 假设顾客选择了“圆形”馒头
mantou.setShape("Round");
}
public void buildFilling(Filling filling) {
// 设置顾客选择的馅料
mantou.setFilling(filling);
}
public Mantou getMantou() {
return mantou;
}
}
交付窗口:需求的采集和产品的交付
// 客户端代码
public class MantouBuilderPatternDemo {
public static void main(String[] args) {
MantouBuilder builder = new CustomMantouBuilder();
builder.buildSize();
builder.buildShape();
Filling redBeanFilling = new RedBeanFilling();
Filling meatFilling = new MeatFilling();
// 顾客可以选择不同的馅料
builder.buildFilling(redBeanFilling);
Mantou mantou1 = builder.getMantou();
mantou1.display();
// 重新使用建造者对象构建另一个不同馅料的馒头
builder.buildFilling(meatFilling);
Mantou mantou2 = builder.getMantou();
mantou2.display();
}
}