Skip to content

建造者模式 (Builder Pattern) ​

模式定义 ​

建造者模式是一种创建型设计模式,它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

核心要点 ​

  • 将对象的构建过程封装在 Builder 中
  • 支持链式调用(Fluent API)
  • 适用于参数多的对象创建

实现方式 ​

1. 传统建造者模式 ​

java
// 产品类
public class Computer {
    private String cpu;
    private String ram;
    private String storage;
    private String gpu;
    private String motherboard;

    public Computer(String cpu, String ram, String storage, String gpu, String motherboard) {
        this.cpu = cpu;
        this.ram = ram;
        this.storage = storage;
        this.gpu = gpu;
        this.motherboard = motherboard;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", ram='" + ram + '\'' +
                ", storage='" + storage + '\'' +
                ", gpu='" + gpu + '\'' +
                ", motherboard='" + motherboard + '\'' +
                '}';
    }
}

// 抽象建造者
public abstract class ComputerBuilder {
    protected Computer computer;

    public void createNewComputer() {
        computer = new Computer(null, null, null, null, null);
    }

    public Computer getComputer() {
        return computer;
    }

    public abstract void buildCpu();
    public abstract void buildRam();
    public abstract void buildStorage();
    public abstract void buildGpu();
    public abstract void buildMotherboard();
}

// 具体建造者 - 游戏电脑
public class GamingComputerBuilder extends ComputerBuilder {
    @Override
    public void buildCpu() {
        computer.cpu = "Intel i9-13900K";
    }

    @Override
    public void buildRam() {
        computer.ram = "32GB DDR5";
    }

    @Override
    public void buildStorage() {
        computer.storage = "2TB NVMe SSD";
    }

    @Override
    public void buildGpu() {
        computer.gpu = "NVIDIA RTX 4090";
    }

    @Override
    public void buildMotherboard() {
        computer.motherboard = "ASUS ROG Maximus";
    }
}

// 具体建造者 - 办公电脑
public class OfficeComputerBuilder extends ComputerBuilder {
    @Override
    public void buildCpu() {
        computer.cpu = "Intel i5-13400";
    }

    @Override
    public void buildRam() {
        computer.ram = "16GB DDR4";
    }

    @Override
    public void buildStorage() {
        computer.storage = "512GB SSD";
    }

    @Override
    public void buildGpu() {
        computer.gpu = "集成显卡";
    }

    @Override
    public void buildMotherboard() {
        computer.motherboard = "Intel B660";
    }
}

// 指挥者
public class ComputerDirector {
    private ComputerBuilder builder;

    public ComputerDirector(ComputerBuilder builder) {
        this.builder = builder;
    }

    public void setBuilder(ComputerBuilder builder) {
        this.builder = builder;
    }

    public Computer constructComputer() {
        builder.createNewComputer();
        builder.buildCpu();
        builder.buildRam();
        builder.buildStorage();
        builder.buildGpu();
        builder.buildMotherboard();
        return builder.getComputer();
    }
}

// 测试代码
public class BuilderDemo {
    public static void main(String[] args) {
        // 构建游戏电脑
        ComputerDirector director = new ComputerDirector(new GamingComputerBuilder());
        Computer gamingComputer = director.constructComputer();
        System.out.println("游戏电脑: " + gamingComputer);

        // 构建办公电脑
        director.setBuilder(new OfficeComputerBuilder());
        Computer officeComputer = director.constructComputer();
        System.out.println("办公电脑: " + officeComputer);
    }
}

2. 内部静态类建造者(推荐) ​

这是 Java 中最常见的建造者实现方式,Lombok 的 @Builder 也是基于此实现。

java
public class HttpRequest {
    private final String url;
    private final String method;
    private final Map<String, String> headers;
    private final String body;
    private final int timeout;

    // 私有构造函数
    private HttpRequest(Builder builder) {
        this.url = builder.url;
        this.method = builder.method;
        this.headers = builder.headers;
        this.body = builder.body;
        this.timeout = builder.timeout;
    }

    // 静态内部类 Builder
    public static class Builder {
        // 必填参数
        private final String url;

        // 可选参数,设置默认值
        private String method = "GET";
        private Map<String, String> headers = new HashMap<>();
        private String body = "";
        private int timeout = 30000;

        // 构造函数只接收必填参数
        public Builder(String url) {
            this.url = url;
        }

        // 链式调用设置可选参数
        public Builder method(String method) {
            this.method = method;
            return this;
        }

        public Builder header(String key, String value) {
            this.headers.put(key, value);
            return this;
        }

        public Builder headers(Map<String, String> headers) {
            this.headers.putAll(headers);
            return this;
        }

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

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

        // 构建对象
        public HttpRequest build() {
            return new HttpRequest(this);
        }
    }

    @Override
    public String toString() {
        return "HttpRequest{" +
                "url='" + url + '\'' +
                ", method='" + method + '\'' +
                ", headers=" + headers +
                ", body='" + body + '\'' +
                ", timeout=" + timeout +
                '}';
    }
}

// 使用方式
public class BuilderPatternDemo {
    public static void main(String[] args) {
        // 最简形式
        HttpRequest request1 = new HttpRequest.Builder("https://api.example.com")
                .build();

        // 完整形式
        HttpRequest request2 = new HttpRequest.Builder("https://api.example.com/users")
                .method("POST")
                .header("Content-Type", "application/json")
                .header("Authorization", "Bearer token123")
                .body("{\"name\": \"张三\"}")
                .timeout(5000)
                .build();

        System.out.println(request1);
        System.out.println(request2);
    }
}

3. Step Builder(步骤建造者) ​

当构建过程有明确的步骤顺序时使用。

java
public class NetworkClient {
    private final String host;
    private final int port;
    private final boolean useSsl;
    private final int maxRetries;
    private final int connectTimeout;

    private NetworkClient(StepBuilder builder) {
        this.host = builder.host;
        this.port = builder.port;
        this.useSsl = builder.useSsl;
        this.maxRetries = builder.maxRetries;
        this.connectTimeout = builder.connectTimeout;
    }

    // 步骤接口
    public interface Step1 {
        Step2 host(String host);
    }

    public interface Step2 {
        Step3 port(int port);
    }

    public interface Step4 {
        Step4 useSsl(boolean useSsl);
        Step4 maxRetries(int retries);
        Step4 connectTimeout(int timeout);
        NetworkClient build();
    }

    public static class StepBuilder implements Step1, Step2, Step4 {
        private String host;
        private int port;
        private boolean useSsl = false;
        private int maxRetries = 3;
        private int connectTimeout = 5000;

        private StepBuilder() {}

        public static Step1 create() {
            return new StepBuilder();
        }

        @Override
        public Step2 host(String host) {
            this.host = host;
            return this;
        }

        @Override
        public Step3 port(int port) {
            this.port = port;
            return new Step3(this);
        }

        @Override
        public Step4 useSsl(boolean useSsl) {
            this.useSsl = useSsl;
            return this;
        }

        @Override
        public Step4 maxRetries(int retries) {
            this.maxRetries = retries;
            return this;
        }

        @Override
        public Step4 connectTimeout(int timeout) {
            this.connectTimeout = timeout;
            return this;
        }

        @Override
        public NetworkClient build() {
            if (host == null || host.isEmpty()) {
                throw new IllegalStateException("host is required");
            }
            if (port <= 0) {
                throw new IllegalStateException("port must be positive");
            }
            return new NetworkClient(this);
        }
    }

    // Step3 作为可选步骤的入口
    public static class Step3 implements Step4 {
        private final StepBuilder builder;

        Step3(StepBuilder builder) {
            this.builder = builder;
        }

        @Override
        public Step4 useSsl(boolean useSsl) {
            builder.useSsl = useSsl;
            return this;
        }

        @Override
        public Step4 maxRetries(int retries) {
            builder.maxRetries = retries;
            return this;
        }

        @Override
        public Step4 connectTimeout(int timeout) {
            builder.connectTimeout = timeout;
            return this;
        }

        @Override
        public NetworkClient build() {
            return builder.build();
        }
    }

    @Override
    public String toString() {
        return "NetworkClient{" +
                "host='" + host + '\'' +
                ", port=" + port +
                ", useSsl=" + useSsl +
                ", maxRetries=" + maxRetries +
                ", connectTimeout=" + connectTimeout +
                '}';
    }
}

// 使用
// NetworkClient client = StepBuilder.create()
//         .host("example.com")    // 必须
//         .port(443)              // 必须
//         .useSsl(true)           // 可选
//         .maxRetries(5)          // 可选
//         .build();

JDK 中的建造者模式 ​

StringBuilder ​

java
String result = new StringBuilder()
        .append("Hello")
        .append(" ")
        .append("World")
        .toString();

Stream.Builder ​

java
Stream<String> stream = Stream.<String>builder()
        .add("Java")
        .add("设计模式")
        .add("建造者")
        .build();

Locale.Builder ​

java
Locale locale = new Locale.Builder()
        .setLanguage("zh")
        .setRegion("CN")
        .build();

与 Lombok @Builder ​

java
@Builder
@Data
public class User {
    private String name;
    private int age;
    private String email;
    private String phone;
}

// Lombok 自动生成的使用方式
User user = User.builder()
        .name("张三")
        .age(25)
        .email("zhangsan@example.com")
        .build();

优缺点 ​

优点:

  • 封装性好,客户端不需要知道产品内部细节
  • 链式调用,代码可读性高
  • 可以精细控制构建过程
  • 支持不可变对象的创建

缺点:

  • 会产生额外的 Builder 类,增加代码量
  • 如果产品内部结构复杂,建造者也会很复杂

适用场景 ​

  • 对象有很多可选参数
  • 需要创建不同的表示
  • 构建过程需要多步骤
  • 需要不可变对象