建造者模式
- 理解方式:
- 奶茶对象,奶茶建造者对象
- 不断向奶茶建造者提供需要添加的小料,最后通过 build 函数检测是否能完成构建,生成符合需求的奶茶对象。
- 解决问题:
- 类属性多,构造方法长。
- set 方法配置,可能需要一定的校验。
- 不希望暴露最终对象的 set 方法,避免创建后被修改。
- 分步骤构建对象。
1 建造者模式
1.1 解决的问题
- 类属性多,构造方法长。
- set 方法配置,可能需要一定的校验。
- 不希望暴露最终对象的 set 方法,避免创建后被修改。
- 分步骤构建对象。
下面的 director 类,相当于工厂,利用建造者模式创建对象。
1.2 模式结构

根据需求,自主选择 A-Z 中的任意步骤执行。
1.3 实现方式
public class MilkTea {
private final String type;
private final String size;
private final boolean pearl;
private final boolean ice;
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);
}
}
}用户
public class User {
private void buyMilkTea() {
MilkTea milkTea = new MilkTea.Builder("原味").build();
MilkTea chocolate =new MilkTea.Builder("巧克力味").ice(false).build();
MilkTea strawberry = new MilkTea.Builder("草莓味").size("大杯").pearl(false).ice(true).build();
}
}另一种实现方法:
// 产品类
public class Role {
private String name; // 角色名
private int sex; // 性别:0-男、1-女
private String face;
private String clothe;
public Role(Builder builder) {
this.name = builder.getName();
this.sex = builder.getSex();
this.face = builder.getFace();
this.clothe = builder.getClothe();
}
}
// 建造者类
public class Builder {
private static final int DEFAULT_SEX = 0;
private static final String DEFAULT_FACE = "大众";
private static final String DEFAULT_CLOTHE = "便装";
private String name; // 角色名,必填
private int sex = DEFAULT_SEX; // 性别:0-男、1-女
private String face = DEFAULT_FACE;
private String clothe = DEFAULT_CLOTHE;
public Role build() {
// 将校验逻辑放到这里,必填项、约束条件等,只有都通过了才构建对象
if(name == null || name.isEmpty()) { return null; }
return new Role(this);
}
public String getName() { return name; }
public int getSex() { return sex; }
public String getFace() { return face; }
public String getClothe() { return clothe; }
// 也可以在set方法中进行逻辑校验
public Builder setName(String name) { this.name = name; return this; }
public Builder setSex(int sex) { this.sex = sex; return this; }
public Builder setFace(String face) { this.face = face; return this; }
public Builder setClothe(String clothe) { this.clothe = clothe; return this; }
}
// 测试用例
public class Game {
public static void main(String[] args) {
Role role = new Builder().setName("杰哥").setFace("超勇").build();
}
}1.4 特点
优点:
- 满足开闭原则 (建造者们都相对独立,替换/新增方便)
- 分离创建和使用 (调用方无需了解内部细节,通过统一方法接口调用即可组合成不同的对象实例)
- 可以自由的组合对象的创建过程 (将复杂的创建步骤拆解为单个独立的创建步骤,可自由拼接)
缺点:
- 代码量增加 (属性写两份,类 Double)
- 使用范围有限 (对象存在较多共同点,如果对象实例间差异太大,就不适合使用 Builder 模式了)
- 容易引起超大类;
1.5 和工厂模式的区别
- 建造者模式 → 用于创建 **
一种类型** 的复杂对象,通过设置不同的可选参数,定制化地创建不同的对象; - 工厂模式 → 用于创建 **
不同但是类型相关** 的对象,由给定的参数来决定创建哪种类型的对象;
顾客进一家餐馆点餐,利用工厂模式,根据用户的不同选择,来制作不同的事物,如披萨、汉堡、沙拉。对于披萨来说,用户有各种配料可以定制,如芝士、西红柿、起司等,我们通过建造者模式根据用户选择的不同配料来制作披萨。
1.6 优缺点
优点:
- 你可以分步创建对象,暂缓创建步骤或递归运行创建步骤。
- 生成不同形式的产品时,你可以复用相同的制造代码。
- 单一职责原则。你可以将复杂构造代码从产品的业务逻辑中分离出来。
缺点:
- 由于该模式需要新增多个类,因此代码整体复杂程度会有所增加。
1.7 应用场景
场景 1:避免重叠构造器的出现
class Pizza {
Pizza(int size) { ... }
Pizza(int size, boolean cheese) { ... }
Pizza(int size, boolean cheese, boolean pepperoni) { ... }场景 2:创建大致相同,具体细节不同的产品
基本生成器接口中定义了所有可能的制造步骤,具体生成器将实现这些步骤来制造特定形式的产品。同时,主管类将负责管理制造步骤的顺序。
场景 3:分步骤构建事物
你可以延迟执行某些步骤而不会影响最终产品。