引言
在软件开发过程中,我们经常面临着构建复杂对象的问题。这些对象可能具有多个属性,并且在创建过程中可能需要进行一系列复杂的初始化步骤。为了简化这个过程,我们可以使用设计模式中的建造者模式。
建造者模式是一种创建型模式,它将对象的构建过程与其表示分离,以便相同的构建过程可以创建不同的表示。在本文中,我们将深入探讨建造者模式的概念、结构和用法,并通过具体的示例来说明其实际应用。
建造者模式的概念
建造者模式,,又叫生成器模式,通过将对象的构建过程委派给不同的建造者,从而使得每个建造者只负责完成特定部分的构建工作。这样一来,我们可以将复杂对象的构建过程分解为多个简单的步骤,每个步骤由对应的建造者来完成。最终,所有的建造者协同工作,完成整个对象的构建。
建造者模式的结构
建造者模式由以下几个核心角色组成:
产品(Product):表示被构建的复杂对象。该对象通常包含多个属性,这些属性可能在构建过程中被设置。
抽象建造者(Builder):定义了构建复杂对象的抽象接口。该接口包含了构建对象各个部分的方法。
具体建造者(Concrete Builder):实现了建造者接口。该类负责构建复杂对象的各个部分,并提供一个方法用于返回构建完成的对象。
指挥者(Director):负责使用建造者接口构建复杂对象。它不直接与产品交互,而是通过调用建造者的方法来构建对象。
以下是建造者模式的结构示意图:
建造者模式的应用场景
建造者模式适用于以下情况:
当需要构建的对象具有复杂的内部结构,并且需要按照一定的顺序进行构建时,可以使用建造者模式来简化构建过程。
当需要创建的对象可以有不同的表示时,可以使用建造者模式来隔离对象的构建和表示,从而使得同样的构建过程可以创建不同的表示。
示例:构建汽车对象
为了更好地理解建造者模式,让我们以构建汽车对象为例进行说明。假设我们需要构建一辆汽车,该汽车具有以下属性:品牌、型号、颜色和价格。
首先,我们定义汽车对象的属性及其访问器方法:
public class Car {
private String brand;
private String model;
private String color;
private double price;
// 省略属性的访问器方法
}
然后,我们定义抽象建造者接口,该接口包含构建汽车各个部分的抽象方法:
public interface CarBuilder {
void buildBrand(String brand);
void buildModel(String model);
void buildColor(String color);
void buildPrice(double price);
Car getResult();
}
接下来,我们实现具体建造者类,负责构建汽车对象的各个部分:
public class SedanCarBuilder implements CarBuilder {
private Car car;
public SedanCarBuilder() {
this.car = new Car();
}
@Override
public void buildBrand(String brand) {
car.setBrand(brand);
}
@Override
public void buildModel(String model) {
car.setModel(model);
}
@Override
public void buildColor(String color) {
car.setColor(color);
}
@Override
public void buildPrice(double price) {
car.setPrice(price);
}
@Override
public Car getResult() {
return car;
}
}
最后,我们定义指挥者类,负责使用建造者接口构建复杂对象:
public class CarDirector {
public Car buildCar(CarBuilder builder, String brand, String model, String color, double price) {
builder.buildBrand(brand);
builder.buildModel(model);
builder.buildColor(color);
builder.buildPrice(price);
return builder.getResult();
}
}
现在,我们可以通过以下代码来构建汽车对象:
CarBuilder builder = new SedanCarBuilder();
CarDirector director = new CarDirector();
Car car = director.buildCar(builder, "Toyota", "Camry", "Red", 30000.0);
System.out.println(car.getBrand()); // 输出:Toyota
System.out.println(car.getModel()); // 输出:Camry
System.out.println(car.getColor()); // 输出:Red
System.out.println(car.getPrice()); // 输出:30000.0
通过使用建造者模式,我们可以将复杂对象的构建过程与其表示分离,使得构建过程更加灵活和可控。
对象构建
在日常开发中,你是不是会经常看到下面这种代码:
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.curry.springbootswagger.controller"))
.paths(PathSelectors.any())
.build();
是不是很优美?学会了 Builder 模式之后,你也可以通过这种方式进行对象构建。它是通过变种的 Builder 模式实现的。先不解释了,我们先用 Builder 模式来实现跟上述的对象构建,使用学生类为例。
学生对象代码:
public class Student {
private String name;
private int age;
private int num;
private String email;
// 提供一个静态builder方法
public static Student.Builder builder() {
return new Student.Builder();
}
// 外部调用builder类的属性接口进行设值。
public static class Builder{
private String name;
private int age;
private int num;
private String email;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder age(int age) {
this.age = age;
return this;
}
public Builder num(int num) {
this.num = num;
return this;
}
public Builder email(String email) {
this.email = email;
return this;
}
public Student build() {
// 将builder对象传入到学生构造函数
return new Student(this);
}
}
// 私有化构造器
private Student(Builder builder) {
name = builder.name;
age = builder.age;
num = builder.num;
email = builder.email;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", num=" + num +
", email='" + email + '\'' +
'}';
}
}
调用代码:
public static void student(){
Student student = Student.builder().name("平头哥").num(1).age(18).email("平头哥@163.com").build();
System.out.println(student);
}
可以看到,变种 Builder 模式包括以下内容:
在要构建的类内部创建一个静态内部类 Builder
静态内部类的参数与构建类一致
构建类的构造参数是 静态内部类,使用静态内部类的变量一一赋值给构建类
静态内部类提供参数的 setter 方法,并且返回值是当前 Builder 对象
最终提供一个 build 方法构建一个构建类的对象,参数是当前 Builder 对象
可能你会说,这种写法实现太麻烦了,确实需要我们写很多额外的代码,好在前辈们已经开发出了lombok来拯救我们,我们只需要引入lombok插件,然后在实体类上添加@Builder注解,你就可以使用 Builder 模式构建对象了。
总结
建造者模式是一种创建型模式,它将对象的构建过程与其表示分离。通过使用建造者模式,我们可以将复杂对象的构建过程分解为多个简单的步骤,从而使得构建过程更加灵活和可控。
在实际应用中,建造者模式常常用于构建复杂的对象,例如:XML解析器、SQL查询生成器等。
建造者模式的优缺点
优点
在建造者模式中, 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象
可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程
增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”
缺点
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
领取专属 10元无门槛券
私享最新 技术干货