Java建造者模式案例怎么实操

wen java案例 32

Java建造者模式案例实操:从理论到项目的完整指南

目录导读

  • 建造者模式的核心概念与适用场景
  • 经典案例:复杂对象的分步构建(含代码)
  • Lombok @Builder 注解的实战应用
  • 建造者模式与工厂模式的区别对比
  • 常见陷阱与最佳实践(含问答)
  • 何时该用建造者模式

建造者模式的核心概念与适用场景

建造者模式(Builder Pattern)属于创建型设计模式,它允许你分步骤创建复杂对象,将对象的构造过程与表示分离。

Java建造者模式案例怎么实操

适用场景

  • 对象有多个构造参数(尤其超过4个)
  • 参数存在可选或必填组合
  • 对象构造需要分步骤执行(如组装汽车)
  • 希望避免“伸缩构造函数”反模式

核心角色

  • Product(产品)——最终要创建的对象
  • Builder(抽象建造者)——声明构造步骤
  • ConcreteBuilder(具体建造者)——实现构造步骤
  • Director(指挥者)——控制构造顺序(可选)

经典案例:复杂对象的分步构建

假设我们需要构建一个 Computer 对象,它有CPU、GPU、内存、硬盘、操作系统等属性,其中有些为必填,有些可选。

第一步:定义产品类

public class Computer {
    // 必填参数
    private String cpu;
    private String gpu;
    private int ram;
    // 可选参数
    private int storage;
    private String os;
    // 私有构造器,只允许通过Builder创建
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.gpu = builder.gpu;
        this.ram = builder.ram;
        this.storage = builder.storage;
        this.os = builder.os;
    }
}

第二步:实现静态内部Builder类

public class Computer {
    // ... 省略属性
    public static class Builder {
        // 必填参数
        private String cpu;
        private String gpu;
        private int ram;
        // 可选参数(设置默认值)
        private int storage = 256;
        private String os = "Windows 11";
        // 必填参数的构造方法
        public Builder(String cpu, String gpu, int ram) {
            this.cpu = cpu;
            this.gpu = gpu;
            this.ram = ram;
        }
        // 为可选参数提供setter方法(链式调用)
        public Builder storage(int val) {
            storage = val;
            return this;
        }
        public Builder os(String val) {
            os = val;
            return this;
        }
        // 构建最终对象
        public Computer build() {
            return new Computer(this);
        }
    }
}

第三步:客户端使用

Computer gamingPC = new Computer.Builder("i7-13700", "RTX 4080", 32)
        .storage(1024)
        .os("Windows 11 Pro")
        .build();
Computer officePC = new Computer.Builder("i5-13400", "GTX 1660", 16)
        .build(); // 仅必填参数

优势

  • 参数顺序无关——通过方法名明确参数含义
  • 可选参数灵活——不必须设置所有字段
  • 对象不可变——无setter方法,通过builder完成所有设置

Lombok @Builder 注解的实战应用

在Spring Boot项目中,更推荐使用Lombok注解简化开发。

示例:使用Lombok实现

import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class User {
    private Long id;
    private String username;
    @Builder.Default
    private String email = "default@example.com";
    private int age;
}

使用方式

User user = User.builder()
        .username("张三")
        .email("zhangsan@example.com")
        .age(25)
        .build();
User defaultUser = User.builder()
        .username("李四")
        .build(); // email取默认值

注意:Lombok的@Builder默认不会给你“必填参数校验”,需要添加@Builder(toBuilder=true)配合自定义校验注解。


建造者模式与工厂模式的区别对比

很多开发者容易混淆这两个模式,我们通过表格清晰比较:

对比维度 建造者模式 工厂模式
关注点 对象的构建过程 对象的创建类型
复杂度 适合复杂对象(多参数) 适合简单对象或同类产品簇
灵活性 可控制构建顺序和步骤 返回完整对象,不可控步骤
典型应用 开发配置类、Request/Response对象 数据库连接池、日志记录器
代码特征 链式调用(.a().b().build()) 单一方法(.create())

何时用建造者模式?

  • 当你需要“分步骤构建”或“可选参数组合”
  • 当你发现构造方法参数超过4个且部分可选

何时用工厂模式?

  • 当你需要“根据类型创建不同子类”
  • 当你希望封装对象创建逻辑(如单例约束)

常见陷阱与最佳实践(含问答)

Q1:Builder类应该放在Product内部还是外部?

回答:推荐放在Product内部作为静态内部类,理由:

  • 访问私有构造函数更简单
  • 与产品类紧密耦合,便于维护
  • 防止外部类随意访问Builder

Q2:为什么需要build()方法做校验?

回答:build()方法虽然是最后一步,但可以拦截无效状态:

public Computer build() {
    if (cpu == null || gpu == null) {
        throw new IllegalStateException("CPU和GPU为必填项");
    }
    if (ram <= 0) {
        throw new IllegalArgumentException("内存必须大于0");
    }
    return new Computer(this);
}

Q3:如何实现不可变对象?

回答

  1. 将所有字段设置为private final
  2. 不提供setter方法
  3. Builder类方法返回this实现链式调用
  4. 在构造器中做防御性拷贝(针对集合类型)

Q4:Lombok的@Builder有哪些坑?

回答

  • 不支持泛型Builder直接实例化(需要自定义Builder类型)
  • @Builder.Default对集合类型默认值无效(需显式初始化如ArrayList<>()
  • 对于集成其他注解(如@AllArgsConstructor),要小心冲突
  1. 必填参数通过构造器传递,避免运行时遗漏
  2. 链式方法返回Builder自身,保持流畅性
  3. 在build()方法做参数校验,而不是分散在每个setter中
  4. Builder类应该保持final,防止继承破坏不变性
  5. 对于不可变对象,禁止在对象内部暴露Builder的引用

何时该用建造者模式

  • 当对象构造参数超过3个(特别是可选参数混合)
  • 当对象需要分步骤构建(如生成复杂报告)
  • 当希望创建不可变对象(无setter、final字段)
  • 当代码中反复出现“伸缩构造函数”(如new X(a,b,c,d,e, null, null, f)
  • 不要用于简单对象(参数少于3个且全必填)
  • 不要与工厂模式混淆(工厂解决“类型”,建造者解决“构造过程”)

通过本文案例,你应该能够:

  1. 手写一个完整的Builder模式
  2. 在Spring Boot项目中熟练使用Lombok @Builder
  3. 区分建造者模式与工厂模式的适用场景
  4. 避免常见的设计陷阱

最后练习:尝试用Builder模式改造你项目中的某个DTO/配置类,你会立刻感受到代码可读性的提升。

抱歉,评论功能暂时关闭!