前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式-建造者模式

设计模式-建造者模式

作者头像
架构狂人
发布2023-10-10 09:48:37
2530
发布2023-10-10 09:48:37
举报
文章被收录于专栏:架构狂人

引言

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

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

建造者模式的概念

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

建造者模式的结构

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

  • 产品(Product):表示被构建的复杂对象。该对象通常包含多个属性,这些属性可能在构建过程中被设置。
  • 抽象建造者(Builder):定义了构建复杂对象的抽象接口。该接口包含了构建对象各个部分的方法。
  • 具体建造者(Concrete Builder):实现了建造者接口。该类负责构建复杂对象的各个部分,并提供一个方法用于返回构建完成的对象。
  • 指挥者(Director):负责使用建造者接口构建复杂对象。它不直接与产品交互,而是通过调用建造者的方法来构建对象。

以下是建造者模式的结构示意图:

建造者模式的应用场景

建造者模式适用于以下情况:

  1. 当需要构建的对象具有复杂的内部结构,并且需要按照一定的顺序进行构建时,可以使用建造者模式来简化构建过程。
  2. 当需要创建的对象可以有不同的表示时,可以使用建造者模式来隔离对象的构建和表示,从而使得同样的构建过程可以创建不同的表示。

示例:构建汽车对象

为了更好地理解建造者模式,让我们以构建汽车对象为例进行说明。假设我们需要构建一辆汽车,该汽车具有以下属性:品牌、型号、颜色和价格。

首先,我们定义汽车对象的属性及其访问器方法:

代码语言:javascript
复制
public class Car {
    private String brand;
    private String model;
    private String color;
    private double price;

    // 省略属性的访问器方法
}

然后,我们定义抽象建造者接口,该接口包含构建汽车各个部分的抽象方法:

代码语言:javascript
复制
public interface CarBuilder {
    void buildBrand(String brand);
    void buildModel(String model);
    void buildColor(String color);
    void buildPrice(double price);
    Car getResult();
}

接下来,我们实现具体建造者类,负责构建汽车对象的各个部分:

代码语言:javascript
复制
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;
    }
}

最后,我们定义指挥者类,负责使用建造者接口构建复杂对象:

代码语言:javascript
复制
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();
    }
}

现在,我们可以通过以下代码来构建汽车对象:

代码语言:javascript
复制
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

通过使用建造者模式,我们可以将复杂对象的构建过程与其表示分离,使得构建过程更加灵活和可控。

对象构建

在日常开发中,你是不是会经常看到下面这种代码:

代码语言:javascript
复制
return new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(apiInfo())
        .select()
        .apis(RequestHandlerSelectors.basePackage("com.curry.springbootswagger.controller"))
        .paths(PathSelectors.any())
        .build();

是不是很优美?学会了 Builder 模式之后,你也可以通过这种方式进行对象构建。它是通过变种的 Builder 模式实现的。先不解释了,我们先用 Builder 模式来实现跟上述的对象构建,使用学生类为例。

学生对象代码:

代码语言:javascript
复制
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 + '\'' +
                '}';
    }
}

调用代码:

代码语言:javascript
复制
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查询生成器等。

建造者模式的优缺点

优点

  • 在建造者模式中, 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
  • 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象
  • 可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程
  • 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”

缺点

  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 顶尖架构师栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 建造者模式的概念
  • 建造者模式的结构
  • 建造者模式的应用场景
  • 示例:构建汽车对象
  • 对象构建
  • 总结
  • 建造者模式的优缺点
    • 优点
      • 缺点
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档