首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

设计模式-建造者模式

引言

在软件开发过程中,我们经常面临着构建复杂对象的问题。这些对象可能具有多个属性,并且在创建过程中可能需要进行一系列复杂的初始化步骤。为了简化这个过程,我们可以使用设计模式中的建造者模式

建造者模式是一种创建型模式,它将对象的构建过程与其表示分离,以便相同的构建过程可以创建不同的表示。在本文中,我们将深入探讨建造者模式的概念、结构和用法,并通过具体的示例来说明其实际应用。

建造者模式的概念

建造者模式,,又叫生成器模式,通过将对象的构建过程委派给不同的建造者,从而使得每个建造者只负责完成特定部分的构建工作。这样一来,我们可以将复杂对象的构建过程分解为多个简单的步骤,每个步骤由对应的建造者来完成。最终,所有的建造者协同工作,完成整个对象的构建。

建造者模式的结构

建造者模式由以下几个核心角色组成:

产品(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查询生成器等。

建造者模式的优缺点

优点

在建造者模式中, 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象

每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象

可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程

增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”

缺点

建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。

如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/Oa4PwVocznn-YKmyXu8osgug0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券