设计模式之建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,旨在将一个复杂对象的构建过程与其表示分离。它允许通过一步步地构造对象,而不需要暴露对象的内部细节和构建过程。通常,这个模式适用于创建对象时需要多个步骤,而这些步骤是独立于对象类型的。

建造者模式的核心思想是:将复杂对象的创建过程分解成多个简单的步骤,并通过一个"建造者"来逐步构建这些步骤,从而得到最终的复杂对象。这个模式特别适合于需要动态创建不同类型的对象,且这些对象的构建过程可能涉及多个变化和不同的配置选项。

1. 建造者模式的结构

建造者模式通常由以下几个角色组成:

  1. Product(产品类):表示复杂对象的最终表示。建造者模式的目的是将这个复杂对象的创建过程封装起来,最终生成一个完整的产品。

  2. Builder(建造者):声明构建产品的抽象步骤,通常是一个接口或抽象类,定义了构建产品的各种部件的方法。

  3. ConcreteBuilder(具体建造者) :实现了 Builder 接口,完成具体的构建过程。每个具体建造者都负责一步步地构建一个产品实例,并且在最终返回产品时,会把各个部件组合成一个完整的对象。

  4. Director(指挥者) :负责指挥 Builder 的构建过程,按照特定的顺序调用 Builder 中的构建步骤。Director 类不参与产品的具体构建工作,它只关心构建的顺序和流程。

  5. Client(客户端) :通过 Director 来控制建造过程,最终得到复杂的产品对象。

2. 建造者模式的实现

2.1 例子:建造一个复杂的 Computer 对象

假设我们要创建一个 Computer 对象,该对象包含多个部件:处理器(CPU)、内存(RAM)、硬盘(Storage)等。每个部件的配置可以不同,并且它们的创建过程可能较为复杂。在这种情况下,建造者模式可以帮助我们一步步构建这个对象。

2.2 代码实现
  • 产品类
java 复制代码
public class Computer {
    private String CPU;
    private String RAM;
    private String Storage;

    public void setCPU(String CPU) {
        this.CPU = CPU;
    }

    public void setRAM(String RAM) {
        this.RAM = RAM;
    }

    public void setStorage(String Storage) {
        this.Storage = Storage;
    }

    @Override
    public String toString() {
        return "Computer [CPU=" + CPU + ", RAM=" + RAM + ", Storage=" + Storage + "]";
    }
}
  • 建造者接口
java 复制代码
public interface Builder {
    Computer computer = new Computer();
    void buildCPU();
    void buildRAM();
    void buildStorage();

    public Computer build();
}
  • 具体建造者类
java 复制代码
public class GamingComputerBuilder implements Builder{
     @Override
    public void buildCPU() {
        computer.setCPU("Intel i9");
    }

    @Override
    public void buildRAM() {
        computer.setRAM("32GB");
    }

    @Override
    public void buildStorage() {
        computer.setStorage("1TB SSD");
    }

    @Override
    public Computer build() {
        return computer;
    }
}
java 复制代码
public class OfficeComputerBuilder implements Builder{
    @Override
    public void buildCPU() {
        computer.setCPU("Intel i5");
    }

    @Override
    public void buildRAM() {
        computer.setRAM("8GB");
    }

    @Override
    public void buildStorage() {
        computer.setStorage("500GB HDD");
    }

    @Override
    public Computer build() {
        return computer;
    }
}
  • 指挥者类
java 复制代码
public class Director {
    private Builder builder;

    public Director(Builder builder){
        this.builder = builder;
    }

    public Computer construct(){
        builder.buildCPU();
        builder.buildRAM();
        builder.buildStorage();
        return builder.build();
    }
}
  • 测试程序
java 复制代码
public class Client {
    public static void main(String[] args) {
        //通过选择不同的构造器,实现不同产品的构筑
        // Director director = new Director(new GamingComputerBuilder());
        Director director = new Director(new OfficeComputerBuilder());

        Computer computer = director.construct();
        System.out.println(computer);
    }
}
2.3 运行结果
复制代码

在这个示例中:

  • Computer 类是复杂对象,它由多个部件(如 CPU、RAM、Storage)组成。
  • Builder 是构建 Computer 的抽象接口,定义了如何构建不同的部件。
  • GamingComputerBuilderOfficeComputerBuilderBuilder 接口的具体实现,负责创建不同配置的 Computer 对象。
  • Director 负责指挥构建过程,它会调用 Builder 中的方法按特定的顺序构建 Computer
  • 最终,客户端通过 Director 获取到构建好的 Computer 对象。

3. 建造者模式的优缺点

优点:
  1. 分离了复杂对象的构建与表示 :客户端只需要了解 DirectorBuilder,而不需要关心构建的细节。

  2. 灵活性高 :可以通过不同的 Builder 实现类,灵活地创建各种配置的对象,满足不同需求。

  3. 可读性强:每一步构建操作都明确地分开了,避免了将所有构建步骤堆叠在一起的情况,从而提高了代码的可读性和可维护性。

  4. 支持增量构建:每个建造者都可以支持增量构建,客户端可以控制每个构建步骤的细节,甚至动态调整对象的构建过程。

缺点:
  1. 类的数量增加 :为了实现建造者模式,通常会需要多个 Builder 类及 Director 类,这会导致类的数量增多,增加了系统的复杂度。

  2. 不适合所有情况:如果对象的构建非常简单,或者构建过程并不复杂,使用建造者模式可能显得过于复杂和冗余。

  3. 无法动态调整构建步骤:建造者模式通常在编译时就确定了构建的步骤顺序,因此它对动态调整和灵活变化的需求支持较差。

4. 应用场景

建造者模式适合以下场景:

  1. 对象构建过程复杂且有多个部分:例如,创建一个复杂的产品或对象,该对象由多个部件或配置组成。

  2. 需要构建不同表示的产品:当你需要构建不同的产品(例如,游戏电脑和办公电脑),这些产品具有相同的构建步骤,但部件的配置不同。

  3. 产品的构建过程独立于产品的具体类:如果你希望产品的构建过程与产品的具体类型分开,这时建造者模式非常适用。

5.建造者模式拓展

除了上述使用方式外,建造者模式在开发中还有一个常用的使用方式,就是当一个类构造器需要传入很多参数时,如果直接创建这个类的实例,代码可读性会非常差,而且很容易引入错误,此时就可以利用建造者模式进行重构。

手机类重构示例
  • 手机类
java 复制代码
package com.tian.pattern.builder.demo2;


public class Phone {

    private String cpu;
    private String screen;
    private String memory;
    private String mainboard;

    //私有构造方法
    private Phone(Builder builder) {
        this.cpu = builder.cpu;
        this.screen = builder.screen;
        this.memory = builder.memory;
        this.mainboard = builder.mainboard;
    }

    @Override
    public String toString() {
        return "Phone{" +
                "cpu='" + cpu + '\'' +
                ", screen='" + screen + '\'' +
                ", memory='" + memory + '\'' +
                ", mainboard='" + mainboard + '\'' +
                '}';
    }

    public static final class Builder {
        private String cpu;
        private String screen;
        private String memory;
        private String mainboard;

        public Builder cpu(String cpu) {
            this.cpu = cpu;
            return this;
        }

        public Builder screen(String screen) {
            this.screen = screen;
            return this;
        }
        public Builder memory(String memory) {
            this.memory = memory;
            return this;
        }
        public Builder mainboard(String mainboard) {
            this.mainboard = mainboard;
            return this;
        }

        //使用构建者创建Phone对象
        public Phone build() {
            return new Phone(this);
        }
    }
}
  • 测试类
java 复制代码
public class Client {
    public static void main(String[] args) {
        Phone phone = new Phone.Builder()
                .setCpu("intel")
                .setScreen("三星屏幕")
                .setMemory("金士顿内存条")
                .setMainboard("华硕主板")
                .build();

        System.out.println(phone);
    }
}
相关推荐
rockmelodies15 小时前
亿赛通脚本远程调试配置技巧
java·亿赛通·debug调试
❥ღ Komo·15 小时前
K8s蓝绿发布实战:零停机部署秘籍
java·开发语言
小安同学iter15 小时前
天机学堂-排行榜功能-day08(六)
java·redis·微服务·zset·排行榜·unlink·天机学堂
hgz071015 小时前
Spring Boot Starter机制
java·spring boot·后端
daxiang1209220515 小时前
Spring boot服务启动报错 java.lang.StackOverflowError 原因分析
java·spring boot·后端
我家领养了个白胖胖15 小时前
极简集成大模型!Spring AI Alibaba ChatClient 快速上手指南
java·后端·ai编程
jiayong2315 小时前
Markdown编辑完全指南
java·编辑器
heartbeat..16 小时前
深入理解 Redisson:分布式锁原理、特性与生产级应用(Java 版)
java·分布式·线程·redisson·
一代明君Kevin学长16 小时前
快速自定义一个带进度监控的文件资源类
java·前端·后端·python·文件上传·文件服务·文件流
未来之窗软件服务16 小时前
幽冥大陆(四十九)PHP打造Java的Jar实践——东方仙盟筑基期
java·php·jar·仙盟创梦ide·东方仙盟·东方仙盟sdk·东方仙盟一体化