Skip to content

建造者模式解决的是"构造一个参数又多、又有可选参数的复杂对象"的痛点,Lombok 的 @BuilderStringBuilder、OkHttp 的 Request.Builder 都是它。这篇把它讲清楚:它和工厂模式的区别在哪、链式调用怎么来的。

一、解决什么问题

当一个对象的构造参数很多、又有可选参数时,传统的构造函数会变得很难用:

java
// 痛点:参数多、顺序难记、可选参数要用 null 占位
Computer c = new Computer("i7", "16G", "512G", null, null, true, null, "NVIDIA");
//                         ↑ 第4、5个参数是啥?传 null 是为了占位?可读性极差

三个痛点:

  1. 参数多、顺序难记:8 个参数谁记得清第几个是啥
  2. 可选参数要用 null 占位:不想设置的参数也得传个 null
  3. 重载构造函数爆炸:不同参数组合要写一堆重载构造函数

建造者模式用链式调用解决:想设哪个设哪个,参数名见名知意,可选参数直接不调。

二、建造者模式怎么落地

java
public class Computer {
    private String cpu;
    private String memory;
    private String disk;
    private String gpu;          // 可选

    private Computer(Builder builder) {          // 私有构造,只让 Builder 建
        this.cpu = builder.cpu;
        this.memory = builder.memory;
        this.disk = builder.disk;
        this.gpu = builder.gpu;
    }

    // 建造者内部类
    public static class Builder {
        private String cpu;
        private String memory;
        private String disk;
        private String gpu;

        public Builder cpu(String cpu) { this.cpu = cpu; return this; }          // 返回 this 实现链式
        public Builder memory(String m) { this.memory = m; return this; }
        public Builder disk(String d) { this.disk = d; return this; }
        public Builder gpu(String g) { this.gpu = g; return this; }

        public Computer build() { return new Computer(this); }                    // 最终构建
    }
}

// 使用:链式调用,见名知意,可选参数直接不写
Computer c = new Computer.Builder()
    .cpu("i7")
    .memory("16G")
    .disk("512G")
    .gpu("NVIDIA")     // 可选,不写就不设
    .build();

核心两点

  • Builder 的每个 setter 返回 this——这是"链式调用"的来源
  • build() 方法最后调用私有构造,产出目标对象

三、Lombok @Builder 一行搞定

手写 Builder 很啰嗦,实际项目都用 Lombok:

java
@Builder
public class Computer {
    private String cpu;
    private String memory;
    private String disk;
    private String gpu;
}

// 用法和手写完全一样
Computer c = Computer.builder().cpu("i7").memory("16G").build();

@Builder 编译时自动生成上面的 Builder 内部类,一行注解省掉几十行样板代码。

建造者模式:Builder 链式设参,build() 最终产出对象

四、建造者 vs 工厂(易混)

两者都是创建型、都是"不直接 new",但关注点不同

维度工厂模式建造者模式
关注创建哪个对象(选型)创建这个对象的复杂组装(步骤)
参数通常参数简单参数多、有可选
典型PayFactory.create("alipay")Computer.builder().cpu().memory().build()

一句话:工厂管"选谁造",建造者管"怎么一步步组装"。一个对象参数多、有可选参数,就用建造者;要屏蔽"具体创建哪个子类",用工厂。工厂模式的详解见《工厂模式》。

小结

  • 建造者解决"参数多 + 可选参数"的构造痛点,核心是链式调用
  • Builder 的 setter 返回 this 实现链式,build() 最终产出对象
  • Lombok @Builder 一行注解自动生成 Builder
  • 与工厂区别:工厂"选谁造",建造者"怎么组装"

下一步可以看同为创建型的《原型模式》——它和建造者/工厂不同,是"复制一个已有对象"而不是"从零构建"(文章整理中)。