Skip to content
Method约 1 分钟0 个小节更新于 2026/06/19在线编辑

建造者模式

建造者模式用于一步一步构建复杂对象,并把构建过程和对象本身分离。

它特别适合构造参数很多、参数可选、对象创建步骤有顺序要求的场景。

解决什么问题

如果一个类构造参数很多,直接使用构造方法会很难读:

java
OrderQuery query = new OrderQuery(1L, "PAID", null, 1, 20, true, false);

调用方很难知道每个参数是什么意思,也容易传错顺序。

建造者模式可以让对象创建变成链式表达:

java
OrderQuery query = OrderQuery.builder()
        .userId(1L)
        .status("PAID")
        .pageNo(1)
        .pageSize(20)
        .includeItems(true)
        .build();

基本结构

text
Product:最终要创建的复杂对象
Builder:负责一步一步收集参数
build():校验参数并创建 Product

传统 GoF 版本里还有 Director 指挥者,用来固定构建流程。实际 Java 业务开发中,更多使用链式 Builder。

Java 示例

java
public class OrderQuery {
    private final Long userId;
    private final String status;
    private final int pageNo;
    private final int pageSize;
    private final boolean includeItems;

    private OrderQuery(Builder builder) {
        this.userId = builder.userId;
        this.status = builder.status;
        this.pageNo = builder.pageNo;
        this.pageSize = builder.pageSize;
        this.includeItems = builder.includeItems;
    }

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
        private Long userId;
        private String status;
        private int pageNo = 1;
        private int pageSize = 20;
        private boolean includeItems;

        public Builder userId(Long userId) {
            this.userId = userId;
            return this;
        }

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

        public Builder pageNo(int pageNo) {
            this.pageNo = pageNo;
            return this;
        }

        public Builder pageSize(int pageSize) {
            this.pageSize = pageSize;
            return this;
        }

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

        public OrderQuery build() {
            if (pageNo <= 0) {
                throw new IllegalArgumentException("pageNo must be greater than 0");
            }
            if (pageSize <= 0 || pageSize > 100) {
                throw new IllegalArgumentException("pageSize must be between 1 and 100");
            }
            return new OrderQuery(this);
        }
    }
}

使用场景

  • 查询条件对象。
  • HTTP 请求参数对象。
  • 配置对象。
  • 构造参数很多的 DTO、VO、Command。
  • 对象创建前需要做统一校验。

优点

  • 调用代码可读性好。
  • 可选参数不用写大量重载构造方法。
  • 可以在 build() 中集中校验。
  • 对象可以设计成不可变,线程安全性更好。

缺点

  • 会增加 Builder 类。
  • 简单对象没必要使用。
  • 如果字段很多但没有校验和语义,可能只是把臃肿换了个地方。

和工厂模式的区别

模式关注点
工厂模式创建哪一种对象
建造者模式一个复杂对象如何一步步构建

如果只是根据类型选择实现,用工厂。如果是同一个对象参数复杂,用建造者。

实战注意

现在很多项目会用 Lombok:

java
@Builder
public class OrderQuery {
    private Long userId;
    private String status;
    private Integer pageNo;
    private Integer pageSize;
}

Lombok 可以减少模板代码,但业务校验仍然要认真设计,不能只为了链式调用而滥用 Builder。

以工程实践沉淀知识,以文档复盘成长。