Java 建造者模式从入门到实战(后端必备)

前言:建造者模式是Java后端开发中最常用的创建型设计模式之一,核心解决“复杂对象创建繁琐”的问题。无论是日常开发中的POJO构建、框架底层的API设计,还是面试中的高频提问,它都无处不在。本文从入门到实战,结合Java真实开发场景,带你吃透建造者模式,看完直接能用、能说、能面试。

一、为什么需要建造者模式?(痛点直击)

做Java开发,你一定遇到过这样的问题:

  • 实体类参数太多(比如10+个字段),构造器冗长,可读性差,调用时容易传错参数顺序;

  • 用setter方法赋值,代码冗余,且无法保证对象不可变(setter可随时修改属性);

  • 多构造器重叠(重载),维护困难,新增参数时需要修改多个构造器;

  • 复杂对象的创建和组装过程混乱,耦合度高,难以维护。

而建造者模式,就是为解决这些痛点而生——将复杂对象的创建和组装分离,通过“链式调用”一步步构建对象,兼顾优雅性和安全性

二、建造者模式核心概念(极简理解)

建造者模式的核心思想:“搭积木”式构建对象。把复杂对象拆分成多个简单组件,分步骤构建,最后组装成完整对象。

标准建造者模式有4个核心角色(理论层面),但Java实际开发中,我们几乎不用这么复杂,重点掌握简化版即可:

  1. Product(产品):需要构建的复杂对象(比如User、Order实体);

  2. Builder(抽象建造者):定义构建产品的抽象方法(规范步骤);

  3. ConcreteBuilder(具体建造者):实现抽象方法,完成具体组件的构建和组装;

  4. Director(指挥者):控制构建流程,调用建造者的方法完成对象创建(实际开发中可省略,直接由Builder控制)。

重点:Java后端开发中,最常用的是“链式建造者”,省略抽象建造者和指挥者,直接在产品类中内置具体建造者,实现链式调用,简洁高效。

三、实战一:手写链式建造者(基础必备)

先手动实现一个链式建造者,理解其底层原理,后续用Lombok简化会更清晰。以常见的User实体为例,包含必选参数和可选参数:

/**
 * 产品类:User(复杂对象)
 * 特点:构造器私有,无setter,保证不可变
 */
public class User {
    // 必选参数(必须传入)
    private final Long id;
    // 可选参数(可选择性设置)
    private final String name;
    private final Integer age;
    private final String phone;
    private final String address;

    // 构造器私有:只能通过建造者创建对象
    private User(Builder builder) {
        this.id = builder.id;
        this.name = builder.name;
        this.age = builder.age;
        this.phone = builder.phone;
        this.address = builder.address;
    }

    // 内置建造者(核心)
    public static class Builder {
        // 必选参数(必须在构造器中传入)
        private final Long id;
        // 可选参数(默认值可省略,也可设置默认值)
        private String name;
        private Integer age;
        private String phone;
        private String address;

        // 建造者构造器:传入必选参数
        public Builder(Long id) {
            this.id = id;
        }

        // 可选参数链式方法:返回Builder本身,实现链式调用
        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder age(Integer age) {
            this.age = age;
            return this;
        }

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

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

        // 构建产品:返回最终的User对象
        public User build() {
            // 可在此处添加参数校验(比如id不为null、age合法等)
            if (id == null) {
                throw new IllegalArgumentException("用户ID不能为空");
            }
            return new User(this);
        }
    }

    // getter方法:只提供查询,不提供修改(保证不可变)
    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

    public String getPhone() {
        return phone;
    }

    public String getAddress() {
        return address;
    }
}

使用方式(链式调用,优雅简洁)

public class BuilderTest {
    public static void main(String[] args) {
        // 1. 必选参数传入建造者,可选参数链式设置,最后build()创建对象
        User user = new User.Builder(1001L)
                .name("张三")
                .age(25)
                .phone("13800138000")
                .address("北京市海淀区")
                .build();

        // 2. 可选参数可省略(灵活)
        User user2 = new User.Builder(1002L)
                .name("李四")
                .build();

        System.out.println(user.getName()); // 张三
        System.out.println(user2.getAge()); // null(未设置)
    }
}

手写建造者核心要点

  • 产品类构造器私有,禁止外部直接new对象;

  • 必选参数放入建造者的构造器,保证必须传入;

  • 可选参数提供链式方法,返回Builder本身;

  • build()方法中可添加参数校验,保证对象合法性;

  • 产品类只提供getter,不提供setter,保证对象不可变。

四、实战二:Lombok @Builder(Java后端最主流用法)

实际项目中,没人会手动写建造者(太繁琐),直接用Lombok的@Builder注解,一键生成链式建造者,代码量骤减。

1. 引入Lombok依赖(pom.xml)

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

2. 注解使用(一行搞定建造者)

import lombok.Builder;
import lombok.Data;

/**
 * 用Lombok @Builder生成建造者
 * @Data:生成getter、setter、toString等(可选,根据需求添加)
 * @Builder:生成链式建造者
 */
@Data
@Builder
public class User {
    // 必选参数(无特殊设置,调用时必须传入)
    private Long id;
    // 可选参数
    private String name;
    private Integer age;
    private String phone;
    private String address;
}

3. 使用方式(和手写版完全一致)

public class LombokBuilderTest {
    public static void main(String[] args) {
        User user = User.builder()
                .id(1001L)
                .name("张三")
                .age(25)
                .phone("13800138000")
                .build();

        System.out.println(user);
    }
}

Lombok @Builder 注意事项

  • @Builder会自动生成私有构造器、Builder内部类和链式方法;

  • 如果需要必选参数强制传入,可结合@NonNull注解(比如@NonNull private Long id);

  • @Builder可与@Data、@NoArgsConstructor、@AllArgsConstructor搭配使用(注意冲突,建议用@Data即可);

  • IDEA需安装Lombok插件,否则会提示报错(插件市场搜索Lombok安装重启即可)。

五、实战三:框架中的建造者模式(面试必说)

建造者模式在Java主流框架中大量应用,面试时能说出1-2个,会显得你理解更深刻。

1. JDK自带:StringBuilder / StringBuffer

最基础、最常见的建造者模式应用,append()方法就是链式建造:

// StringBuilder的append()就是链式建造
StringBuilder sb = new StringBuilder();
sb.append("Java")
  .append("建造者模式")
  .append("实战");
String result = sb.toString();

2. MyBatis / MyBatis-Plus

查询条件构建、SQL构建,全是建造者模式的思想:

// MyBatis-Plus:LambdaQueryChainWrapper(链式查询)
List<User> userList = new LambdaQueryChainWrapper<>(userMapper)
        .eq(User::getName, "张三")
        .ge(User::getAge, 18)
        .orderByDesc(User::getId)
        .list();

// MyBatis:SqlSessionFactoryBuilder
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
        .build(inputStream);

3. Spring 框架

Spring中大量使用建造者模式构建复杂对象:

// BeanDefinitionBuilder:构建Bean定义
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
builder.addPropertyValue("id", 1001L)
       .addPropertyValue("name", "张三");
BeanDefinition beanDefinition = builder.getBeanDefinition();

// MockMvc:测试接口时的链式构建
mockMvc.perform(MockMvcRequestBuilders.post("/user/login")
        .param("username", "admin")
        .param("password", "123456"))
        .andExpect(status().isOk());

4. OkHttp 框架

HTTP请求构建,链式调用非常优雅:

// Request.Builder:构建HTTP请求
Request request = new Request.Builder()
        .url("https://www.baidu.com")
        .get()
        .addHeader("Content-Type", "application/json")
        .build();

六、建造者模式面试高频考点(必背)

1. 建造者模式的核心优势?

  • 可读性强:链式调用,代码优雅,一眼能看出对象的构建过程;

  • 灵活性高:可选参数可自由组合,无需创建多个构造器;

  • 安全性高:可保证对象不可变(无setter),且能在build()中做参数校验;

  • 解耦:将对象的创建和组装分离,降低耦合度,便于维护和扩展。

2. 建造者模式和工厂模式的区别?(高频)

核心区别:工厂模式关注“创建对象”,建造者模式关注“组装对象”

  • 工厂模式:直接返回一个完整的对象,不关心对象的组装过程;

  • 建造者模式:分步骤构建对象,可灵活控制对象的各个组件,关注“怎么组装”。

举例:工厂模式直接给你一台完整的手机;建造者模式给你零件,一步步组装成手机,可选择不同的屏幕、电池。

3. 什么时候用建造者模式?

  • 对象参数多(尤其是可选参数多),构造器冗长;

  • 需要构建不可变对象(无setter);

  • 复杂对象的创建和组装过程需要灵活控制;

  • 希望代码更优雅、可读性更强(链式调用)。

七、总结(实战+面试双达标)

对于Java后端开发者来说,建造者模式不是“花里胡哨”的设计模式,而是日常开发必备的工具

  1. 基础:理解链式建造者的原理,能手写简单版本;

  2. 实战:熟练使用Lombok @Builder,简化开发;

  3. 面试:能说出框架中的应用,区分建造者和工厂模式。

记住一句话:参数多、要优雅、需不可变,就用建造者模式。它能帮你解决构造器冗余、代码混乱的问题,让你的代码更具可读性和可维护性。

补充:常见问题解决

  • 问题1:Lombok @Builder生成的对象,无法用无参构造器?
    解决:添加@NoArgsConstructor,或用User.builder().build()创建空对象(需保证无必选参数)。

  • 问题2:如何强制必选参数?
    解决:结合@NonNull注解,或手写建造者(将必选参数放入建造者构造器)。

  • 问题3:建造者模式和构造器、setter的区别?
    解决:构造器适合参数少的场景;setter适合对象可修改的场景;建造者适合参数多、不可变、需优雅构建的场景。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐