在面向对象设计中,建造者模式(Builder Pattern) 是一种非常经典的设计模式,特别适用于需要构造复杂对象的场景。Lombok 提供的 @Builder 注解极大简化了 Builder 模式的实现,而 toBuilder = true 则进一步增强了它的灵活性,使我们能够基于已有对象快速创建新的变体。
本文将深入探讨 @Builder 背后的设计模式,适用场景、不适用场景,以及 @Builder(toBuilder = true) 的使用方法。
一、Builder 模式简介
Builder 模式 是一种创建型设计模式,主要用于构造具有多个可选参数或复杂结构的对象。其核心思想是通过一个 Builder 类一步步设置对象的属性,最后构造出一个完整的对象。
传统 Builder 模式的实现
以构建一个复杂的 Car 类为例,传统的 Builder 模式如下:
public class Car {
    private final String engine;
    private final int seats;
    private final String color;
    private Car(CarBuilder builder) {
        this.engine = builder.engine;
        this.seats = builder.seats;
        this.color = builder.color;
    }
    public static class CarBuilder {
        private String engine;
        private int seats;
        private String color;
        public CarBuilder engine(String engine) {
            this.engine = engine;
            return this;
        }
        public CarBuilder seats(int seats) {
            this.seats = seats;
            return this;
        }
        public CarBuilder color(String color) {
            this.color = color;
            return this;
        }
        public Car build() {
            return new Car(this);
        }
    }
}
 
使用方式:
Car car = new Car.CarBuilder()
                 .engine("V8")
                 .seats(4)
                 .color("Red")
                 .build();
 
虽然功能强大,但手动编写 Builder 模式的代码往往繁琐冗长。Lombok 的 @Builder 注解可以让我们完全摆脱这一繁琐过程。
二、Lombok 的 @Builder 简化实现
 
Lombok 的 @Builder 注解会自动为目标类生成一个静态内部类,作为 Builder 类,同时提供链式方法和 build() 方法。
基本用法
import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class Car {
    private final String engine;
    private final int seats;
    private final String color;
}
public class Main {
    public static void main(String[] args) {
        Car car = Car.builder()
                     .engine("V8")
                     .seats(4)
                     .color("Red")
                     .build();
        System.out.println(car);
    }
}
 
输出:
Car(engine=V8, seats=4, color=Red)
 
可以看到,@Builder 自动生成了 CarBuilder 类,并支持链式调用,大幅简化了代码。
三、@Builder(toBuilder = true) 的增强功能
 
当 @Builder 配置了 toBuilder = true 时,Lombok 会为目标类生成一个 toBuilder() 方法,允许基于已有对象创建一个新的 Builder。这种增强功能特别适用于需要对不可变对象进行部分修改的场景。
示例代码
@Builder(toBuilder = true)
@ToString
public class Car {
    private final String engine;
    private final int seats;
    private final String color;
}
public class Main {
    public static void main(String[] args) {
        // 创建初始对象
        Car car = Car.builder()
                     .engine("V8")
                     .seats(4)
                     .color("Red")
                     .build();
        // 基于现有对象修改部分字段
        Car updatedCar = car.toBuilder()
                            .color("Blue")
                            .build();
        System.out.println("Original Car: " + car);
        System.out.println("Updated Car: " + updatedCar);
    }
}
 
输出:
Original Car: Car(engine=V8, seats=4, color=Red)
Updated Car: Car(engine=V8, seats=4, color=Blue)
 
toBuilder() 方法的作用:
- 返回一个 Builder 对象,其中的属性初始值为当前对象的值。
 - 可以灵活修改部分属性值,构造新的对象。
 
四、Builder 模式的适用场景
1. 需要构造复杂对象时
当一个类的构造方法包含多个参数,特别是可选参数时,使用 Builder 模式可以避免构造器参数混乱问题。
例如,构造一个具有多个可选属性的 Car 类:
Car car = Car.builder()
             .engine("V8")
             .seats(4)
             .color("Red")
             .build();
 
2. 需要不可变对象时
Builder 模式是构造不可变对象的最佳选择。通过 final 修饰属性和 @Builder,可以确保对象一旦创建,所有字段值都不可更改。
3. 需要对象的灵活更新时
配合 toBuilder = true,可以在保持不可变特性的同时灵活更新对象。例如:
Car updatedCar = car.toBuilder()
                    .seats(5)
                    .build();
 
这种场景常见于配置类、请求对象、数据模型等需要频繁修改但又需要保持线程安全的地方。
五、Builder 模式的不适用场景
尽管 Builder 模式功能强大,但它并不适合所有情况:
1. 简单对象的构造
对于只有少量字段的类,使用 Builder 反而显得繁琐。例如:
class User {
    private String name;
    private int age;
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
 
对于这样的简单对象,直接使用构造方法更简洁高效。
2. 对象生命周期短,频繁创建
在高性能场景中,如果对象生命周期非常短,且需要频繁创建,Builder 的链式调用可能带来额外开销。
3. 过度设计的风险
如果类的复杂性并不需要 Builder 模式,但仍然引入 Builder,则可能导致代码的复杂性增加。例如,对某些工具类、纯数据类使用 Builder 可能是过度设计。
六、总结
1. @Builder 与设计模式
 
- Builder 模式非常适合构造复杂对象或不可变对象。
 - Lombok 的 
@Builder大幅简化了 Builder 模式的实现,让开发者专注于业务逻辑。 
2. toBuilder = true 的增强
 
- 提供了灵活性,允许基于现有对象创建新的变体。
 - 在不可变对象的更新场景中尤为实用。
 
3. 适用与不适用场景
- 适用场景:复杂对象构造、不可变对象、多参数类。
 - 不适用场景:简单类、高性能频繁创建对象场景、过度设计。
 
4. 推荐实践
- 对于复杂业务实体或配置类,使用 
@Builder和toBuilder = true是最佳实践。 - 对于简单类或数据模型,直接使用构造方法或工厂方法即可。
 
通过合理地选择和应用 Builder 模式,可以有效提升代码的可读性、可维护性以及灵活性。善用 Lombok 的 @Builder,可以让你的代码更加优雅高效!









