建造者模式详解
一、建造者模式概述
建造者模式(Builder Pattern)是一种创建型设计模式,它将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
核心特点
- 分离构建过程:将复杂对象的构建步骤分解
- 灵活配置:通过不同建造者实现不同配置
- 控制构建顺序:可以精确控制对象的创建过程
- 链式调用:通常使用流式接口(Fluent Interface)
二、建造者模式的结构
主要角色
- Product:最终要构建的复杂对象
- Builder:抽象建造者接口
- ConcreteBuilder:具体建造者实现
- Director:指导者(可选),控制构建过程
三、建造者模式的实现
1. 基本实现方式
// 产品类
public class Computer {private String CPU;private String RAM;private String storage;// 私有构造方法private Computer(Builder builder) {this.CPU = builder.CPU;this.RAM = builder.RAM;this.storage = builder.storage;}// 建造者静态内部类public static class Builder {private String CPU;private String RAM;private String storage;public Builder setCPU(String CPU) {this.CPU = CPU;return this;}public Builder setRAM(String RAM) {this.RAM = RAM;return this;}public Builder setStorage(String storage) {this.storage = storage;return this;}public Computer build() {return new Computer(this);}}// getter方法public String getCPU() {return CPU;}
}// 使用示例
Computer computer = new Computer.Builder().setCPU("Intel i7").setRAM("16GB").setStorage("512GB SSD").build();
2. 带指导者的实现方式
// 产品类
public class Pizza {private String dough;private String sauce;private String topping;public void setDough(String dough) {this.dough = dough;}public void setSauce(String sauce) {this.sauce = sauce;}public void setTopping(String topping) {this.topping = topping;}
}// 抽象建造者
public interface PizzaBuilder {void buildDough();void buildSauce();void buildTopping();Pizza getPizza();
}// 具体建造者
public class HawaiianPizzaBuilder implements PizzaBuilder {private Pizza pizza = new Pizza();public void buildDough() {pizza.setDough("cross");}public void buildSauce() {pizza.setSauce("mild");}public void buildTopping() {pizza.setTopping("ham+pineapple");}public Pizza getPizza() {return pizza;}
}// 指导者
public class Waiter {private PizzaBuilder pizzaBuilder;public void setPizzaBuilder(PizzaBuilder pb) {pizzaBuilder = pb;}public Pizza getPizza() {return pizzaBuilder.getPizza();}public void constructPizza() {pizzaBuilder.buildDough();pizzaBuilder.buildSauce();pizzaBuilder.buildTopping();}
}// 使用示例
Waiter waiter = new Waiter();
PizzaBuilder hawaiianBuilder = new HawaiianPizzaBuilder();waiter.setPizzaBuilder(hawaiianBuilder);
waiter.constructPizza();
Pizza pizza = waiter.getPizza();
四、建造者模式的应用场景
1. 复杂对象创建
// 邮件对象构建
public class Email {private String from;private String to;private String subject;private String body;private List<String> attachments;private Email(Builder builder) {this.from = builder.from;this.to = builder.to;this.subject = builder.subject;this.body = builder.body;this.attachments = builder.attachments;}public static class Builder {private String from;private String to;private String subject = "";private String body = "";private List<String> attachments = new ArrayList<>();public Builder(String from, String to) {this.from = from;this.to = to;}public Builder subject(String subject) {this.subject = subject;return this;}public Builder body(String body) {this.body = body;return this;}public Builder addAttachment(String file) {attachments.add(file);return this;}public Email build() {return new Email(this);}}
}
2. 配置对象构建
// 数据库配置构建
public class DatabaseConfig {private final String host;private final int port;private final String username;private final String password;private final int maxConnections;private final boolean useSSL;private DatabaseConfig(Builder builder) {this.host = builder.host;this.port = builder.port;this.username = builder.username;this.password = builder.password;this.maxConnections = builder.maxConnections;this.useSSL = builder.useSSL;}public static class Builder {private String host = "localhost";private int port = 3306;private String username;private String password;private int maxConnections = 10;private boolean useSSL = false;public Builder setHost(String host) {this.host = host;return this;}public Builder setPort(int port) {this.port = port;return this;}// ...其他setter方法public DatabaseConfig build() {if (username == null || password == null) {throw new IllegalStateException("用户名和密码必须设置");}return new DatabaseConfig(this);}}
}
3. 不可变对象构建
// 不可变用户对象
public final class User {private final String firstName;private final String lastName;private final int age;private final String phone;private final String address;private User(Builder builder) {this.firstName = builder.firstName;this.lastName = builder.lastName;this.age = builder.age;this.phone = builder.phone;this.address = builder.address;}public static class Builder {private final String firstName;private final String lastName;private int age = 0;private String phone = "";private String address = "";public Builder(String firstName, String lastName) {this.firstName = firstName;this.lastName = lastName;}public Builder age(int age) {this.age = age;return this;}// ...其他属性设置方法public User build() {return new User(this);}}
}
五、建造者模式的变体
1. Lombok @Builder 注解
@Builder
public class Person {private String name;private int age;private String address;
}// 使用方式
Person person = Person.builder().name("张三").age(30).address("北京").build();
2. 阶梯建造者
public interface CarBuilder {EngineBuilder withEngine();
}public interface EngineBuilder {ColorBuilder withColor();
}public interface ColorBuilder {Car build();
}
六、建造者模式的优缺点
优点
- 封装性好:构建过程与表示分离
- 扩展性好:新增构建步骤不影响现有代码
- 控制精细:可以精确控制构建过程
- 可读性强:链式调用提高代码可读性
缺点
- 代码量增加:需要额外编写Builder类
- 适用范围有限:仅适用于复杂对象创建
- 学习成本:对新手可能不够直观
七、建造者模式的最佳实践
- 参数较多时使用:当构造函数参数超过4个时考虑使用
- 创建不可变对象:特别适合构建不可变对象
- 与工厂模式结合:复杂对象可以先Builder后Factory
- 保持Builder简洁:避免在Builder中包含业务逻辑
- 考虑使用Lombok:简化样板代码的编写
八、总结
建造者模式是处理复杂对象创建的利器,特别适用于:
- 需要创建包含多个部件的复杂对象
- 对象有多个变体或配置选项
- 需要创建不可变对象
- 希望提供清晰的创建API
在实际开发中,建造者模式经常用于:
- 配置对象的构建
- DTO对象的创建
- 测试数据的准备
- 复杂领域模型的实例化
正确使用建造者模式可以显著提高代码的可读性和可维护性,是Java开发者工具箱中的重要设计模式。