什么是建造者模式
建造者模式简介
建造者(Builder)模式是一种创建型设计模式,它允许构造复杂对象的步骤被分解,并允许相同的构建过程创建不同的表示。这种模式主要用于减少构造函数的参数数量,避免创建包含大量参数的对象时出现的“参数地狱”。用一句话概括就是建造者模式的目的是为了分离对象的属性与创建过程。
建造者模式的由来
建造者模式是构造方法的一种替代方案,为什么需要建造者模式,我们可以想,假设有一个对象里面有20个属性:
- 属性1
- 属性2
- …
- 属性20
对开发者来说这不是疯了,也就是说我要去使用这个对象,我得去了解每个属性的含义,然后在构造函数或者Setter中一个一个去指定。更加复杂的场景是,这些属性之间是有关联的,比如属性1=A,那么属性2只能等于B/C/D,这样对于开发者来说更是增加了学习成本,开源产品这样的一个对象相信不会有太多开发者去使用。
为了解决以上的痛点,建造者模式应运而生,对象中属性多,但是通常重要的只有几个,因此建造者模式会让开发者指定一些比较重要的属性或者让开发者指定某几个对象类型,然后让建造者去实现复杂的构建对象的过程,这就是对象的属性与创建分离。这样对于开发者而言隐藏了复杂的对象构建细节,降低了学习成本,同时提升了代码的可复用性。
建造者模式的结构
建造者模式的结构需要产品(Product)、抽象建造者(Builder)、具体建造者(ConcreteBuilder)、指挥者(Director)四个角色。
产品(Product):表明需要构建的产品对象
抽象建造者(Builder):抽象出来的构建者类,用于定义创建对象所需的步骤以及创建的步骤的调用过程
具体建造者(ConcreteBuilder):抽象建造者的具体实现,对于不同的创建过程可以用不同的类进行实现
指挥者(Director):使用 Builder 的类,提供给调用方使用,调用方通过使用指挥者来获取产品
简单示例
// 产品类
public class Car {
private String wheels;
private String engine;
private String body;
// 省略getter和setter方法
}
// 抽象建造者
public abstract class CarBuilder {
protected Car car;
public Car getCar() {
return car;
}
public void createNewCar() {
car = new Car();
}
public abstract void buildWheels();
public abstract void buildEngine();
public abstract void buildBody();
}
// 具体建造者
public class SedanCarBuilder extends CarBuilder {
@Override
public void buildWheels() {
car.setWheels("Sedan Wheels");
}
@Override
public void buildEngine() {
car.setEngine("Sedan Engine");
}
@Override
public void buildBody() {
car.setBody("Sedan Body");
}
}
// 指挥者
public class CarDirector {
private CarBuilder builder;
public CarDirector(CarBuilder builder) {
this.builder = builder;
}
public void constructCar() {
builder.createNewCar();
builder.buildBody();
builder.buildEngine();
builder.buildWheels();
}
public Car getCar() {
return builder.getCar();
}
}
// 调用代码
public class BuilderExample {
public static void main(String[] args) {
CarBuilder builder = new SedanCarBuilder();
CarDirector director = new CarDirector(builder);
director.constructCar();
Car car = director.getCar();
// 使用car对象...
}
}
在这个例子中,Car
是产品类,包含了一个汽车需要的各种部分。CarBuilder
是抽象建造者,定义了构建汽车所需的步骤。SedanCarBuilder
是具体建造者,它实现了这些步骤来构建轿车型号的汽车。CarDirector
是指挥者,它接受一个建造者对象,并且指导如何步骤化地构建汽车。最后,客户端代码创建了一个建造者和指挥者,并用它们来构建汽车。
Java中的StringBuilder
是建造者模式的一个经典实例。在构建字符串时,StringBuilder
提供了一种逐步构建字符串的方法,而不是使用多个字符串拼接,这样可以避免创建多余的字符串对象,提高性能。
优缺点
优点
-
客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
-
每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象 。
-
增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
-
可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
缺点
-
复杂性增加:如果原始对象的构造过程本身不复杂,引入建造者模式可能会增加不必要的复杂性。
-
代码冗余:需要编写多个Builder类,特别是当产品变种很多时,会产生大量类文件。
使用场景
-
当创建的对象需要很多步骤,这些步骤需要按特定的顺序执行时。
-
当创建的对象有着复杂的组合时,不同的组合可能需要不同的构建过程和参数。
-
当构建的对象经常变化时,使用建造者模式可以更容易地适应变化。
-
当构建过程需要被封装起来,使得用户不需要了解产品的内部构成细节时。