深入理解设计模式之建造者模式
深入理解设计模式之建造者模式
1. 什么是建造者模式
建造者模式是一种创建型设计模式,它将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。建造者模式允许用户在不知道内部构建细节的情况下,一步步创建复杂对象。
2. 建造者模式的核心组成
- 产品(Product): 被构建的复杂对象
- 抽象建造者(Builder): 定义创建产品各个部分的抽象接口
- 具体建造者(ConcreteBuilder): 实现Builder接口,构建和装配各个部件
- 指挥者(Director): 负责调用适当的建造者来构建产品
3. 为什么使用建造者模式
- 分离复杂对象的构建与表示
- 控制构建过程
- 隐藏产品内部结构的细节
- 解决构造函数参数过多导致的问题
- 创建不可变对象
4. 建造者模式的实现
4.1 经典建造者模式实现
// 产品类
class Computer {private String cpu;private String memory;private String storage;private String gpu;private String motherboard;public void setCpu(String cpu) {this.cpu = cpu;}public void setMemory(String memory) {this.memory = memory;}public void setStorage(String storage) {this.storage = storage;}public void setGpu(String gpu) {this.gpu = gpu;}public void setMotherboard(String motherboard) {this.motherboard = motherboard;}@Overridepublic String toString() {return "Computer{" +"cpu='" + cpu + '\'' +", memory='" + memory + '\'' +", storage='" + storage + '\'' +", gpu='" + gpu + '\'' +", motherboard='" + motherboard + '\'' +'}';}
}// 抽象建造者
interface ComputerBuilder {void buildCpu();void buildMemory();void buildStorage();void buildGpu();void buildMotherboard();Computer getComputer();
}// 具体建造者:高端电脑
class HighEndComputerBuilder implements ComputerBuilder {private Computer computer = new Computer();@Overridepublic void buildCpu() {computer.setCpu("Intel Core i9-12900K");}@Overridepublic void buildMemory() {computer.setMemory("32GB DDR5");}@Overridepublic void buildStorage() {computer.setStorage("2TB NVMe SSD");}@Overridepublic void buildGpu() {computer.setGpu("NVIDIA RTX 4090");}@Overridepublic void buildMotherboard() {computer.setMotherboard("ASUS ROG Maximus Z690");}@Overridepublic Computer getComputer() {return computer;}
}// 具体建造者:经济型电脑
class BudgetComputerBuilder implements ComputerBuilder {private Computer computer = new Computer();@Overridepublic void buildCpu() {computer.setCpu("Intel Core i5-12400");}@Overridepublic void buildMemory() {computer.setMemory("16GB DDR4");}@Overridepublic void buildStorage() {computer.setStorage("500GB SSD");}@Overridepublic void buildGpu() {computer.setGpu("NVIDIA RTX 3060");}@Overridepublic void buildMotherboard() {computer.setMotherboard("MSI B660M");}@Overridepublic Computer getComputer() {return computer;}
}// 指挥者
class ComputerDirector {public Computer buildComputer(ComputerBuilder builder) {builder.buildCpu();builder.buildMemory();builder.buildStorage();builder.buildGpu();builder.buildMotherboard();return builder.getComputer();}
}// 客户端代码
public class ClassicBuilderDemo {public static void main(String[] args) {ComputerDirector director = new ComputerDirector();ComputerBuilder highEndBuilder = new HighEndComputerBuilder();Computer highEndComputer = director.buildComputer(highEndBuilder);System.out.println("High-end Computer: " + highEndComputer);ComputerBuilder budgetBuilder = new BudgetComputerBuilder();Computer budgetComputer = director.buildComputer(budgetBuilder);System.out.println("Budget Computer: " + budgetComputer);}
}
4.2 现代建造者模式(流式接口)
// 产品类
class Person {// 必需参数private final String firstName;private final String lastName;// 可选参数private final int age;private final String address;private final String phone;private final String email;private Person(PersonBuilder builder) {this.firstName = builder.firstName;this.lastName = builder.lastName;this.age = builder.age;this.address = builder.address;this.phone = builder.phone;this.email = builder.email;}@Overridepublic String toString() {return "Person{" +"firstName='" + firstName + '\'' +", lastName='" + lastName + '\'' +", age=" + age +", address='" + address + '\'' +", phone='" + phone + '\'' +", email='" + email + '\'' +'}';}// 静态内部类建造者public static class PersonBuilder {// 必需参数private final String firstName;private final String lastName;// 可选参数 - 初始化为默认值private int age = 0;private String address = "";private String phone = "";private String email = "";// 构造函数传入必需参数public PersonBuilder(String firstName, String lastName) {this.firstName = firstName;this.lastName = lastName;}// 可选参数的设置方法public PersonBuilder age(int age) {this.age = age;return this;}public PersonBuilder address(String address) {this.address = address;return this;}public PersonBuilder phone(String phone) {this.phone = phone;return this;}public PersonBuilder email(String email) {this.email = email;return this;}// 构建方法public Person build() {return new Person(this);}}
}// 客户端代码
public class FluentBuilderDemo {public static void main(String[] args) {Person person1 = new Person.PersonBuilder("John", "Doe").age(30).address("123 Main St, City").phone("555-1234").email("john.doe@example.com").build();Person person2 = new Person.PersonBuilder("Jane", "Smith").age(25).email("jane.smith@example.com").build();System.out.println(person1);System.out.println(person2);}
}
4.3 实际案例:使用建造者模式创建HTTP请求
// 产品:HTTP请求
class HttpRequest {private final String url;private final String method;private final Map<String, String> headers;private final Map<String, String> parameters;private final String body;private final int timeout;private HttpRequest(Builder builder) {this.url = builder.url;this.method = builder.method;this.headers = Collections.unmodifiableMap(builder.headers);this.parameters = Collections.unmodifiableMap(builder.parameters);this.body = builder.body;this.timeout = builder.timeout;}// 获取请求信息的方法public String getUrl() { return url; }public String getMethod() { return method; }public Map<String, String> getHeaders() { return headers; }public Map<String, String> getParameters() { return parameters; }public String getBody() { return body; }public int getTimeout() { return timeout; }@Overridepublic String toString() {return "HttpRequest{" +"url='" + url + '\'' +", method='" + method + '\'' +", headers=" + headers +", parameters=" + parameters +", body='" + body + '\'' +", timeout=" + timeout +'}';}// 建造者public static class Builder {// 必需参数private final String url;// 可选参数 - 初始化为默认值private String method = "GET";private final Map<String, String> headers = new HashMap<>();private final Map<String, String> parameters = new HashMap<>();private String body = "";private int timeout = 30000; // 默认30秒public Builder(String url) {this.url = url;}public Builder method(String method) {this.method = method;return this;}public Builder addHeader(String name, String value) {this.headers.put(name, value);return this;}public Builder addParameter(String name, String value) {this.parameters.put(name, value);return this;}public Builder body(String body) {this.body = body;return this;}public Builder timeout(int timeout) {this.timeout = timeout;return this;}public HttpRequest build() {return new HttpRequest(this);}}
}// 使用示例
public class HttpRequestDemo {public static void main(String[] args) {HttpRequest getRequest = new HttpRequest.Builder("https://api.example.com/users").addHeader("Accept", "application/json").addParameter("page", "1").addParameter("size", "10").timeout(5000).build();HttpRequest postRequest = new HttpRequest.Builder("https://api.example.com/users").method("POST").addHeader("Content-Type", "application/json").addHeader("Authorization", "Bearer token123").body("{\"name\":\"John\",\"email\":\"john@example.com\"}").build();System.out.println(getRequest);System.out.println(postRequest);// 模拟发送请求sendRequest(getRequest);sendRequest(postRequest);}private static void sendRequest(HttpRequest request) {System.out.println("Sending " + request.getMethod() + " request to " + request.getUrl());if (!request.getParameters().isEmpty()) {System.out.println("Parameters: " + request.getParameters());}if (!request.getHeaders().isEmpty()) {System.out.println("Headers: " + request.getHeaders());}if (!request.getBody().isEmpty()) {System.out.println("Body: " + request.getBody());}System.out.println("Timeout: " + request.getTimeout() + "ms");System.out.println("Request sent!");System.out.println("------------------------------");}
}
5. 建造者模式的优缺点
优点
- 分离构建与表示:构建复杂对象的过程和细节被隐藏
- 更好的控制构建过程:可以精细控制构建步骤
- 支持变化的构建过程:不同的建造者可以创建不同表示
- 代码可读性:特别是当有很多参数时,使用建造者模式的代码更清晰
- 参数验证:可以在build()方法中进行参数验证
缺点
- 代码量增加:需要创建Builder类和相关接口
- 对于简单对象可能过度设计:参数较少的对象使用建造者模式可能显得多余
- 构造函数参数和Builder方法参数可能重复
6. 与其他创建型模式的对比
模式 | 建造者模式 | 工厂方法模式 | 抽象工厂模式 |
---|---|---|---|
目的 | 复杂对象的构建 | 创建单个对象 | 创建对象家族 |
关注点 | 如何一步步构建复杂对象 | 对象的创建方法 | 创建相关对象 |
灵活性 | 可以控制构建过程的每一步 | 创建单一产品 | 创建一系列产品 |
复杂度 | 中等 | 低 | 高 |
7. 实际应用场景
- 配置对象创建:如数据库连接配置、网络请求配置
- 不可变对象构建:创建不可变但有多个配置参数的对象
- 多步骤构建:需要多个步骤才能完成的对象构建过程
- 参数可选:大量可选参数的情况
8. Java标准库中的建造者模式
Java标准库中有多处使用了建造者模式:
// StringBuilder示例
StringBuilder sb = new StringBuilder().append("Hello").append(" ").append("World").append("!");
String result = sb.toString();// Java 8 Stream API示例
List<String> names = Arrays.asList("John", "Jane", "Bob", "Alice");
List<String> filteredNames = names.stream().filter(name -> name.startsWith("J")).map(String::toUpperCase).sorted().collect(Collectors.toList());
9. 小结
建造者模式是一种灵活且强大的创建型设计模式,特别适合构建复杂对象或具有多个可选参数的对象。它将对象的构建与表示分离,使得相同的构建过程可以创建不同的表示。在实际开发中,现代建造者模式(流式接口)因其简洁和链式调用的特性而被广泛采用。
当对象构造复杂、有多个参数(特别是可选参数)或需要一步步构建时,建造者模式是一个很好的选择。通过合理使用建造者模式,可以创建出更加灵活、可维护的代码。