定义
Builder模式,即建造者模式,也被称作生成器模式,属于创建型设计模式的一种。它旨在将一个复杂对象的构建过程与其表示过程分离,使得同样的构建过程可以创建不同的表示。此模式的核心思想是将复杂对象的构建分解成一系列步骤,并将这些步骤封装在独立类中,即所谓的建造者类,以实现构建和表示的解耦。
建造者模式的核心在于“变与不变”的分离。在软件系统中,经常面临的情况是某些对象的组成部分(即不变的部分)是固定的,但这些部分的组合方式(即变化的部分)可能会频繁地变化。建造者模式通过将不变的部分封装在抽象建造者接口中,而将变化的部分留给具体建造者类来实现,从而实现了变与不变的分离。
在建造者模式中,通常涉及以下关键角色:
- 产品(Product):这是最终构建出的复杂对象,它包含多个属性和一些核心方法。
- 抽象建造者(Builder):定义创建产品各个部分的接口,规定了构建步骤的框架,不涉及具体实现。
- 具体建造者(ConcreteBuilder):实现了抽象建造者的接口,负责具体构建产品的各个部分,每个具体建造者通常对应产品的特定变体或配置。
- 指挥者(Director):负责管理整个构建过程,确保按照既定步骤和顺序完成产品的构建。
应用示例
以下是一个简化的Java代码示例,用于展示创建者模式在构建计算机对象时的应用:
// 产品:计算机,它包含了CPU、内存和硬盘等属性
public class Computer {
private String cpu;
private String memory;
private String hardDisk;
// 私有构造器,因为我们将通过具体建造者来创建Computer对象
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.memory = builder.memory;
this.hardDisk = builder.hardDisk;
}
public static Builder builder() {
return new Builder();
}
// 静态内部类:具体建造者
public static class Builder {
private String cpu;
private String memory;
private String hardDisk;
// 链式调用的setter方法
public Builder withCpu(String cpu) {
this.cpu = cpu;
return this; // 返回this以实现链式调用
}
public Builder withMemory(String memory) {
this.memory = memory;
return this;
}
public Builder withHardDisk(String hardDisk) {
this.hardDisk = hardDisk;
return this;
}
// 构建并返回产品
public Computer build() {
return new Computer(this);
}
}
// 展示计算机信息的方法
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", memory='" + memory + '\'' +
", hardDisk='" + hardDisk + '\'' +
'}';
}
// 主方法,用于演示如何使用建造者模式创建计算机对象
public static void main(String[] args) {
// 创建一个具体的建造者并设置属性值
Computer computer = Computer.builder()
.withCpu("Intel Core i9")
.withMemory("16GB DDR4")
.withHardDisk("1TB SSD")
.build();
// 打印计算机信息 输出:Computer{cpu='Intel Core i9', memory='16GB DDR4', hardDisk='1TB SSD'}
System.out.println(computer);
}
}
在上述示例中,我们关注了产品和具体建造者的实现,而没有引入抽象建造者和指挥者。这是因为,在构建过程较为简单或不需要多种构建方式的情形下,可以简化建造者模式,将指挥者的职责整合进具体建造者。这种简化有助于减少系统复杂性,但需注意,它可能会破坏单一职责原则并增加组件间的耦合度。
为了引入抽象建造者和指挥者,我们将对上述示例进行以下改造:
- 首先,我们定义一个产品计算机(Computer)。
public class Computer {
private String cpu;
private String memory;
private String hardDisk;
public void setCpu(String cpu) {
this.cpu = cpu;
}
public void setMemory(String memory) {
this.memory = memory;
}
public void setHardDisk(String hardDisk) {
this.hardDisk = hardDisk;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", memory='" + memory + '\'' +
", hardDisk='" + hardDisk + '\'' +
'}';
}
}
- 接着,定义一个抽象建造者(Builder)和具体建造者(ConcreteBuilder)。
public interface Builder {
Builder withCpu(String cpu);
Builder withMemory(String memory);
Builder withHardDisk(String hardDisk);
Computer build();
}
public class ConcreteBuilder implements Builder {
private Computer computer;
public ConcreteBuilder() {
this.computer = new Computer();
}
@Override
public Builder withCpu(String cpu) {
computer.setCpu(cpu);
return this;
}
@Override
public Builder withMemory(String memory) {
computer.setMemory(memory);
return this;
}
@Override
public Builder withHardDisk(String hardDisk) {
computer.setHardDisk(hardDisk);
return this;
}
@Override
public Computer build() {
return computer;
}
}
- 然后,定义一个指挥者(Director)。
public class Director {
private final Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void construct() {
builder.withCpu("Intel Core i9")
.withMemory("16GB DDR4")
.withHardDisk("1TB SSD");
}
}
- 最后,创建一个客户端类来演示如何使用。
public class Client {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct();
Computer computer = builder.build();
// 打印计算机信息 输出:Computer{cpu='Intel Core i9', memory='16GB DDR4', hardDisk='1TB SSD'}
System.out.println(computer);
}
}
优缺点分析
优点:
- 封装性好:建造者模式将复杂对象的构建过程封装在建造者类中,客户端只需要知道建造者接口,而不需要知道具体的构建细节,这降低了客户端与具体构建过程的耦合度。
- 优秀的扩展性:由于建造者模式的构建过程与表示过程分离,因此可以通过定义不同的建造者类来创建不同的表示,这使得系统具有很好的扩展性。此外,具体建造者相互独立,方便扩展,符合开闭原则。
- 便于控制细节风险:在建造者模式中,客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,这有助于降低系统的复杂性并减少出错的可能性。
缺点:
- 对象的构建过程变得更加繁琐:相比直接使用构造器创建对象,使用建造者模式需要调用多个方法来设置对象的属性,这增加了构建对象的步骤和复杂度。如果一个类只有很少的属性,使用建造者模式可能会显得过于繁琐和复杂。
- 一定的使用范围限制:建造者模式要求产品的组件基本相同,如果产品的差异性较大,建造者模式可能就不适用了。此外,如果产品内部变化复杂,建造者也需要同步修改,这会增加后期维护的成本。
总结
建造者模式是一种强大的创建型设计模式,它通过将复杂对象的构建过程分解为一系列步骤,并将这些步骤封装在单独的建造者类中,从而实现了变与不变的分离。这种模式不仅提高了代码的可读性和可维护性,还使得代码更加灵活和易于扩展。在实际开发中,我们应该根据具体需求来选择合适的设计模式,以提高代码质量、降低维护成本。