教程中心 / Java教程 / 建造者模式

建造者模式

10分钟 设计模式

什么是建造者模式?

建造者模式(Builder Pattern)是一种创建型设计模式,它通过链式调用逐步构建复杂对象。当一个类的构造函数参数过多时,使用建造者模式可以让代码更清晰、更易读。

生活比喻

想象你去电脑城组装电脑。你不需要一次性告诉销售员所有配件(CPU、内存、硬盘、显示器),而是一步一步选择:先选CPU,再选内存,...最后确认配置单。建造者模式就像这个"配置单",让复杂的创建过程变得清晰可控。

为什么需要建造者模式?

传统构造函数的痛苦:参数列表太长

// 如果用传统构造函数,创建对象会变成噩梦
User user = new User("张三", 25, true, "北京", "13800001111", 
    "zhang@example.com", "XX公司", true, ...);
// 参数太多,谁知道每个参数是什么意思?

// 而且如果有些参数是可选的:
User user = new User("张三", 25, null, null, null, null, null, null, null);
// 这太难看了!

传统Builder实现

public class User {
    private String name;      // 必填
    private int age;          // 必填
    private String email;     // 可选
    private String phone;     // 可选
    private String address;    // 可选
    private boolean active;   // 可选

    // 私有构造函数,只能通过Builder创建
    private User(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.email = builder.email;
        this.phone = builder.phone;
        this.address = builder.address;
        this.active = builder.active;
    }

    // 静态内部类Builder
    public static class Builder {
        // 必填参数
        private String name;
        private int age;

        // 可选参数,使用默认值
        private String email = "";
        private String phone = "";
        private String address = "";
        private boolean active = true;

        public Builder(String name, int age) {
            this.name = name;
            this.age = age;
        }

        // 链式调用方法
        public Builder email(String email) {
            this.email = email;
            return this;
        }

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

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

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

        public User build() {
            return new User(this);
        }
    }

    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age +
            ", email='" + email + "', phone='" + phone +
            "', address='" + address + "', active=" + active + "}";
    }
}

Builder模式使用

public class BuilderDemo {
    public static void main(String[] args) {
        System.out.println("===== 完整参数 =====");
        User user1 = new User.Builder("张三", 25)
            .email("zhang@example.com")
            .phone("13800138000")
            .address("北京市朝阳区")
            .active(true)
            .build();
        System.out.println("用户1: " + user1);

        System.out.println("\n===== 部分参数 =====");
        User user2 = new User.Builder("李四", 30)
            .email("li@example.com")
            .build();
        System.out.println("用户2: " + user2);

        System.out.println("\n===== 只有必填参数 =====");
        User user3 = new User.Builder("王五", 22)
            .build();
        System.out.println("用户3: " + user3);
    }
}

ComputerBuilder完整示例

再来看一个更复杂的例子——组装电脑配置:

public class Computer {
    private String cpu;        // 必填
    private String ram;        // 必填
    private String storage;     // 可选
    private String display;    // 可选
    private String keyboard;   // 可选
    private boolean hasWifi;   // 可选
    private boolean hasBluetooth;

    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.ram = builder.ram;
        this.storage = builder.storage;
        this.display = builder.display;
        this.keyboard = builder.keyboard;
        this.hasWifi = builder.hasWifi;
        this.hasBluetooth = builder.hasBluetooth;
    }

    public static class Builder {
        private String cpu;
        private String ram;
        private String storage = "256GB SSD";
        private String display = "14 inch";
        private String keyboard = "默认键盘";
        private boolean hasWifi = true;
        private boolean hasBluetooth = true;

        public Builder(String cpu, String ram) {
            this.cpu = cpu;
            this.ram = ram;
        }

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

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

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

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

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

        public Computer build() {
            return new Computer(this);
        }
    }

    @Override
    public String toString() {
        return "Computer{" +
            "cpu='" + cpu + '\'' +
            ", ram='" + ram + '\'' +
            ", storage='" + storage + '\'' +
            ", display='" + display + '\'' +
            ", keyboard='" + keyboard + '\'' +
            ", hasWifi=" + hasWifi +
            ", hasBluetooth=" + hasBluetooth +
            '}';
    }
}

// 使用
public class ComputerBuilderDemo {
    public static void main(String[] args) {
        Computer gaming = new Computer.Builder("Intel i9", "32GB")
            .storage("2TB SSD")
            .display("27 inch 144Hz")
            .keyboard("机械键盘")
            .wifi(true)
            .bluetooth(true)
            .build();
        System.out.println("游戏电脑: " + gaming);

        Computer office = new Computer.Builder("Intel i5", "16GB")
            .build();
        System.out.println("办公电脑: " + office);
    }
}

建造者模式的优势

代码清晰

链式调用,参数名称明确,无需记住参数顺序

可选参数

可以轻松处理可选参数,不用传null

验证逻辑

可以在build()方法中集中验证

不可变对象

对象在build()时一次性创建完成,保证不可变性

Lombok @Builder(推荐)

如果你使用Lombok,可以自动生成Builder代码:

import lombok.Builder;
import lombok.ToString;

@Builder
@ToString
public class UserLombok {
    private String name;
    private int age;
    private String email;
    private String phone;
}

// Lombok自动生成:
UserLombok user = UserLombok.builder()
    .name("张三")
    .age(25)
    .email("zhang@example.com")
    .build();
System.out.println(user);

小结

  • 建造者模式通过链式调用逐步构建复杂对象
  • 解决构造函数参数过多的问题
  • 可以设置必填参数可选参数
  • 提供清晰的代码可读性,参数名称一目了然
  • Lombok @Builder注解可以自动生成Builder代码
☕ Java 在线代码编辑器
📝 运行结果