Java 中的建造者模式
简介
在软件开发中,创建对象的过程有时会变得复杂,特别是当对象有许多属性,并且这些属性之间存在复杂的依赖关系时。建造者模式(Builder Pattern)作为一种创建型设计模式,提供了一种创建对象的优雅方式,它将对象的构建和表示分离,使得构建过程更加清晰、可维护和可扩展。本文将深入探讨 Java 中的建造者模式,包括其基础概念、使用方法、常见实践以及最佳实践。
目录
- 基础概念
- 使用方法
- 常见实践
- 最佳实践
- 小结
- 参考资料
基础概念
建造者模式主要包含以下几个角色: - 产品(Product):需要创建的复杂对象。 - 抽象建造者(Builder):定义创建产品各个部分的抽象方法。 - 具体建造者(ConcreteBuilder):实现抽象建造者的方法,负责具体的产品构建过程。 - 指挥者(Director):负责调用建造者的方法来构建产品,控制构建的顺序。
使用方法
代码示例
下面通过一个创建电脑对象的例子来展示建造者模式的使用。
产品类(Computer)
public class Computer {
private String cpu;
private String ram;
private String storage;
// 私有构造函数,防止外部直接实例化
private Computer(ComputerBuilder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", ram='" + ram + '\'' +
", storage='" + storage + '\'' +
'}';
}
// 静态内部类,作为建造者
public static class ComputerBuilder {
private String cpu;
private String ram;
private String storage;
public ComputerBuilder setCpu(String cpu) {
this.cpu = cpu;
return this;
}
public ComputerBuilder setRam(String ram) {
this.ram = ram;
return this;
}
public ComputerBuilder setStorage(String storage) {
this.storage = storage;
return this;
}
public Computer build() {
return new Computer(this);
}
}
}
测试代码
public class BuilderPatternDemo {
public static void main(String[] args) {
Computer computer = new Computer.ComputerBuilder()
.setCpu("Intel Core i7")
.setRam("16GB")
.setStorage("512GB SSD")
.build();
System.out.println(computer);
}
}
解析
在上述代码中:
1. Computer
类是产品类,它有 cpu
、ram
和 storage
三个属性,并且构造函数是私有的,防止外部直接创建实例。
2. ComputerBuilder
是 Computer
类的静态内部类,作为具体建造者。它提供了设置各个属性的方法,并且返回 this
,以便链式调用。build
方法用于创建并返回最终的 Computer
对象。
3. 在 main
方法中,通过 Computer.ComputerBuilder
来创建 Computer
对象,代码简洁明了,易于理解和维护。
常见实践
省略指挥者角色
在很多实际应用中,指挥者角色可以省略。因为如果构建过程并不复杂,直接在客户端代码中调用建造者的方法来构建产品会更加简洁。就像上面的 Computer
例子,我们没有使用指挥者角色,而是在 main
方法中直接调用 ComputerBuilder
的方法来构建 Computer
对象。
与工厂模式结合
建造者模式可以和工厂模式结合使用。工厂模式负责创建对象,而建造者模式负责对象的复杂构建过程。例如,一个工厂方法可以返回一个建造者实例,然后客户端通过这个建造者来完成对象的构建。
public class ComputerFactory {
public static Computer.ComputerBuilder getComputerBuilder() {
return new Computer.ComputerBuilder();
}
}
使用时:
public class BuilderAndFactoryDemo {
public static void main(String[] args) {
Computer computer = ComputerFactory.getComputerBuilder()
.setCpu("AMD Ryzen 9")
.setRam("32GB")
.setStorage("1TB NVMe SSD")
.build();
System.out.println(computer);
}
}
最佳实践
链式调用的一致性
在建造者类中,所有设置属性的方法都应该返回 this
,以实现链式调用。这样可以使代码更加简洁和易读。
验证和错误处理
在 build
方法中,应该对构建的对象进行必要的验证。如果对象的某些属性不符合要求,应该抛出适当的异常,以便及时发现和处理问题。
public class ComputerBuilder {
//...
public Computer build() {
if (cpu == null || ram == null || storage == null) {
throw new IllegalArgumentException("CPU, RAM and storage are required");
}
return new Computer(this);
}
}
不可变对象
如果产品对象不需要支持属性的修改,可以将其设计为不可变对象。在构造函数中设置所有属性后,不再提供修改属性的方法,这样可以提高对象的安全性和可维护性。
public class ImmutableComputer {
private final String cpu;
private final String ram;
private final String storage;
public ImmutableComputer(ImmutableComputerBuilder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
}
// getters only
public String getCpu() {
return cpu;
}
public String getRam() {
return ram;
}
public String getStorage() {
return storage;
}
// 静态内部类,作为建造者
public static class ImmutableComputerBuilder {
private String cpu;
private String ram;
private String storage;
// 设置属性方法
public ImmutableComputerBuilder setCpu(String cpu) {
this.cpu = cpu;
return this;
}
public ImmutableComputerBuilder setRam(String ram) {
this.ram = ram;
return this;
}
public ImmutableComputerBuilder setStorage(String storage) {
this.storage = storage;
return this;
}
public ImmutableComputer build() {
if (cpu == null || ram == null || storage == null) {
throw new IllegalArgumentException("CPU, RAM and storage are required");
}
return new ImmutableComputer(this);
}
}
}
小结
建造者模式是 Java 中一种强大的设计模式,它通过将对象的构建和表示分离,使得创建复杂对象的过程更加清晰、可维护和可扩展。通过省略指挥者角色、与工厂模式结合等常见实践,以及遵循链式调用一致性、验证和错误处理、创建不可变对象等最佳实践,可以更好地运用建造者模式来提升代码的质量和可维护性。
参考资料
- 《Effective Java》 by Joshua Bloch
- Wikipedia - Builder Pattern
- Oracle Java Tutorials