1. 建造者模式简介
今天我们将研究 Java 中的建造者模式(Builder 模式
)。Builder 设计模式是一种创建型设计模式,也被称为生成器模式,类似于工厂模式和抽象工厂模式。
该模式用于创建复杂对象,允许用户创建不同类型的对象,同时保持对象的构造过程和表示分离。
2. 建造者模式的产生背景
2.1 工厂模式和抽象工厂模式的缺陷
引入建造者模式是为了解决工厂和抽象工厂设计模式在对象包含大量属性时出现的一些问题。当对象包含大量属性时,工厂和抽象工厂设计模式存在三个主要问题。
- 从客户端程序传递给工厂类的参数太多,这很容易出错,因为大多数情况下,参数的类型是相同的,并且从客户端很难维护参数的顺序。
- 一些参数可能是可选的,但在工厂模式中,我们被迫发送所有参数,并且可选参数需要以 NULL 发送。
- 如果对象很重并且其创建很复杂,那么所有的复杂性都将成为令人困惑的工厂类的一部分。
2.2 建造者模式诞生
我们可以通过提供具有必需参数的构造函数来解决大量参数的问题,然后提供不同的 setter 方法来设置可选参数。这种方法的问题在于,除非明确设置所有属性,否则对象状态将不一致。建造者模式通过提供一种逐步构建对象的方法并提供一种实际返回最终对象的方法,解决了大量可选参数和不一致状态的问题。
3. 建造者模式原理
在Java中,建造者模式可以通过内部类,一个指导者类(Director)和多个建造者类(Builder)实现。
建造者(Builder)模式包含以下4个角色 :
3.1 抽象建造者类(Builder)
这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的部件对象的创建。
3.2 具体建造者类(ConcreteBuilder)
实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供一个方法,返回创建好的负责产品对象。
3.3 产品类(Product)
要创建的复杂对象,可以拥有很多属性。
3.4 指挥者类(Director)
调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建(客户端一般只需要与指挥者进行交互)。
4. 建造者模式的实现示例
让我们依次来构建建造者模式的四大角色:产品类、抽象建造者类(建造者接口)、具体建造者和指导者类。
在下面这个例子中,Product
类代表了一个复杂的对象,它有多个部分组成。Builder
接口定义了构建产品的不同部分的方法。ConcreteBuilder
是具体的建造者,实现了 Builder
接口,负责构建 Product
对象的各个部分。Director
类负责安排已经构建好的部件组装成完整的产品。客户端代码中,我们首先创建了一个建造者实例,然后通过指导者类来构建产品,最后展示构建好的产品。
4.1 产品类
class Product {
private String partA;
private String partB;
private String partC;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void setPartC(String partC) {
this.partC = partC;
}
public void show() {
// 展示产品的方法
}
}
4.2 建造者接口
interface Builder {
void buildPartA();
void buildPartB();
void buildPartC();
Product getResult();
}
4.3 具体建造者
class ConcreteBuilder implements Builder {
private Product product = new Product();
public void buildPartA() {
product.setPartA("构建部分A");
}
public void buildPartB() {
product.setPartB("构建部分B");
}
public void buildPartC() {
product.setPartC("构建部分C");
}
public Product getResult() {
return product;
}
}
4.4 指导者类
class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
4.5 最后我们写一个客户端代码来运行
public class BuilderPatternExample {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct();
Product product = builder.getResult();
product.show();
}
}
5. 建造者模式优缺点
建造者模式也不是完美的,它存在诸多有点的同时也存在诸多缺点。
5.1 建造者模式的优点
5.1.1 分离构建和表示
建造者模式可以将对象的构建过程与其表示分离开来,使得客户端不必知道产品内部组成的细节,从而实现了产品本身与产品创建过程的解耦。这允许同样的构建过程创建不同的表示形式。
5.1.2 易于扩展
通过添加新的建造器,可以轻松地扩展建造者模式以支持创建新的对象类型。这符合开闭原则,即对扩展开放,对修改关闭。
5.1.3 控制对象的创建过程
建造者模式允许您控制对象的构建过程,确保对象被正确地构建。通过将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
5.1.4 创建复杂对象
使用建造者模式可以创建具有多个组成部分的复杂对象,这些部分可能具有不同的属性和功能。
5.1.5 稳定性强
建造者模式的稳定性很好,通过有效的封装变化,可以取得比较好的稳定性。
5.2 建造者模式的缺点
5.2.1 增加代码量
由于建造者模式需要定义多个类和接口,因此在实现时可能会增加代码量。
5.2.2 影响性能
建造者模式的实现可能会影响性能,因为它需要通过多个对象来构建一个完整的对象。但通常该性能问题可以忽略不记!
5.2.3 类的数量增多
由于将对象的创建过程分解为多个步骤,并将这些步骤封装在独立的建造者类中,因此需要创建多个建造者类,从而增加了类的数量。
5.2.4 建造过程复杂
如果对象的创建过程过于复杂,可能会导致建造者类的建造过程也变得复杂,从而增加了代码的维护难度。
6. 建造者模式与工厂模式区别
建造者模式与工厂模式的区别主要体现在关注点、产品复杂度、以及使用场景上。
6.1 关注点不同
工厂模式
主要关注的是对象的创建过程,它提供一个接口或抽象类来创建一系列相关的对象,而不关心对象的内部结构和组装过程。相比之下,建造者模式
关注的是对象的内部结构和组装过程,通过将产品的内部表象和产品的生成过程分开,允许用户在不了解产品内部细节的情况下,通过配置和组装部件来创建复杂对象。
6.2 产品复杂度不同
工厂模式
通常用于创建单一性质的产品,这些产品具有相似的结构和行为。而建造者模式
适用于创建复杂的对象,这些对象由多个部件组成,并且这些部件的组合方式可以变化,从而产生不同的产品对象。
6.3 使用场景不同
工厂模式
适用于当需要创建的对象具有相同的接口但不同的实现时,例如创建一个动物类,但具体实例可能是狗或猫等。建造者模式
则适用于当对象结构复杂,由多个部分组成,并且这些部分的组装顺序和方式会影响最终产品的功能或表现时,例如构建一个软件或硬件系统,其中涉及多个组件的组装和配置。
综上所述,工厂模式和建造者模式虽然都是用于创建对象的设计模式,但它们在处理对象创建和组装的方式上有所不同,选择使用哪种模式取决于具体的需求和场景。
总结
以上就是关于建造者模式的详细介绍,你学会了吗?从建造者模式的产生背景,原理,以及代码示例、优缺点分析等多维度进行了阐述。相信通过本文的学习,大家对建造者模式有了更加深入的认识!