Java设计模式精讲---03建造者模式

在软件开发中,我们经常需要创建一些包含多个组成部分的复杂对象。比如一台电脑由 CPU、内存、硬盘、显卡等部件组成;一份简历包含基本信息、教育经历、工作经历、项目经验等模块。如果直接通过构造函数或 setter 方法来组装这些对象,不仅会导致代码臃肿、参数混乱,还难以灵活应对不同组合的需求。

今天我们来聊聊一种专门解决这类问题的设计模式 ------建造者模式,看看它如何像 "搭积木" 一样优雅地构建复杂对象。

一、什么是建造者模式

建造者模式的核心思想是:将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建出不同的表示。

简单来说,就是把 "怎么组装零件" 和 "最终组装出什么产品" 分开。比如同样是组装电脑,"先装 CPU 再装内存最后装硬盘" 这个流程可以不变,但可以根据需求组装出 "游戏本"或 "办公本"。

二、建造者模式解决什么问题

假设我们要创建一个Computer类,如果用传统方式创建,可能会写出这样的代码:

java 复制代码
​
// 传统方式:构造函数参数爆炸
public class Computer {
    public Computer(String cpu, String memory, String hardDisk, String gpu, String os) {
        // 初始化逻辑
    }
}

// 使用时需要记住参数顺序,新增参数还要改构造函数
Computer gamePC = new Computer("i9-13900K", "32GB", "1TB SSD", "RTX 4090", "Windows 11");

​

这种方式的问题很明显:

  1. 参数过多,容易传错顺序;
  2. 如果需要创建不同配置(比如办公本不需要独立显卡),得重载多个构造函数,代码冗余;
  3. 构建过程(比如 "必须先装 CPU 才能装内存")无法控制,容易出现无效对象。

而建造者模式就能完美解决这些问题:它将构建步骤拆分,通过 "一步步设置" 的方式组装对象,同时隐藏复杂的构建逻辑。

三、建造者模式的核心角色

建造者模式包含 4 个核心角色,我们用 "组装电脑" 的例子来理解:

  1. 产品 :被构建的复杂对象(比如Computer),包含多个组成部分。

  2. 抽象建造者:定义构建产品的抽象步骤(比如 "装 CPU""装内存"),以及返回最终产品的方法。它不关心具体怎么实现,只规定 "要做哪些事"。

  3. 具体建造者 :实现抽象建造者的步骤,负责具体的零件组装(比如GameComputerBuilder实现 "装高性能 CPU""装独立显卡")。

  4. 指挥者:负责控制构建流程(比如 "先装 CPU→再装内存→最后装系统"),它调用具体建造者的方法,按照固定流程组装产品,用户不需要关心步骤细节。

四、代码实现:用建造者模式组装电脑

我们通过代码来实现 "组装电脑" 的例子,看看建造者模式如何落地。

1. 定义产品

首先是被构建的对象Computer,它包含多个部件:

java 复制代码
// 产品:电脑
public class Computer {
    private String cpu;      // CPU
    private String memory;   // 内存
    private String hardDisk; // 硬盘
    private String gpu;      // 显卡
    private String os;       // 操作系统

    // 私有构造函数,避免外部直接创建
    private Computer() {}

    // getter方法(便于查看结果)
    public String getCpu() { return cpu; }
    public String getMemory() { return memory; }
    public String getHardDisk() { return hardDisk; }
    public String getGpu() { return gpu; }
    public String getOs() { return os; }

    // 内部静态类:用于修改私有属性(建造者需要访问)
    public static class Builder {
        private Computer computer;

        public Builder() {
            computer = new Computer();
        }

        // 逐步设置属性的方法(返回Builder本身,支持链式调用)
        public Builder setCpu(String cpu) {
            computer.cpu = cpu;
            return this;
        }

        public Builder setMemory(String memory) {
            computer.memory = memory;
            return this;
        }

        public Builder setHardDisk(String hardDisk) {
            computer.hardDisk = hardDisk;
            return this;
        }

        public Builder setGpu(String gpu) {
            computer.gpu = gpu;
            return this;
        }

        public Builder setOs(String os) {
            computer.os = os;
            return this;
        }

        // 返回最终构建的产品
        public Computer build() {
            return computer;
        }
    }
}

​

这里用了一个内部静态 Builder 类 (简化版建造者),它可以直接访问Computer的私有属性,同时支持链式调用(每个 set 方法返回Builder本身)。

2. 定义具体建造者

根据需求,我们创建两种具体建造者:游戏本建造者和办公本建造者:

java 复制代码
​
// 具体建造者1:游戏本建造者
public class GameComputerBuilder {
    private Computer.Builder builder;

    public GameComputerBuilder() {
        builder = new Computer.Builder();
    }

    // 构建游戏本的方法(预设高性能配件)
    public void buildGameComputer() {
        builder.setCpu("i9-13900K")
               .setMemory("32GB DDR5")
               .setHardDisk("1TB SSD")
               .setGpu("RTX 4090")
               .setOs("Windows 11");
    }

    // 返回构建好的电脑
    public Computer getResult() {
        return builder.build();
    }
}

// 具体建造者2:办公本建造者
public class OfficeComputerBuilder {
    private Computer.Builder builder;

    public OfficeComputerBuilder() {
        builder = new Computer.Builder();
    }

    // 构建办公本的方法(预设稳定低耗配件)
    public void buildOfficeComputer() {
        builder.setCpu("i5-13400")
               .setMemory("16GB DDR4")
               .setHardDisk("512GB SSD")
               .setGpu("集成显卡")  // 办公本无需独立显卡
               .setOs("Windows 10");
    }

    public Computer getResult() {
        return builder.build();
    }
}

​

3. 定义指挥者

指挥者负责控制构建流程,确保步骤正确:

java 复制代码
​// 指挥者:负责控制电脑组装流程
public class ComputerDirector {
    // 指挥建造者按照流程构建产品
    public Computer construct(GameComputerBuilder builder) {
        builder.buildGameComputer(); // 调用游戏本的构建方法
        return builder.getResult();
    }

    public Computer construct(OfficeComputerBuilder builder) {
        builder.buildOfficeComputer(); // 调用办公本的构建方法
        return builder.getResult();
    }
}

4. 测试代码

最后我们用客户端代码测试一下:

java 复制代码
public class Client {
    public static void main(String[] args) {
        // 创建指挥者
        ComputerDirector director = new ComputerDirector();

        // 构建游戏本
        GameComputerBuilder gameBuilder = new GameComputerBuilder();
        Computer gamePC = director.construct(gameBuilder);
        System.out.println("游戏本配置:");
        System.out.println("CPU:" + gamePC.getCpu());
        System.out.println("显卡:" + gamePC.getGpu());

        // 构建办公本
        OfficeComputerBuilder officeBuilder = new OfficeComputerBuilder();
        Computer officePC = director.construct(officeBuilder);
        System.out.println("\n办公本配置:");
        System.out.println("CPU:" + officePC.getCpu());
        System.out.println("显卡:" + officePC.getGpu());
    }
}

​

输出结果:

复制代码
游戏本配置:
CPU:i9-13900K
显卡:RTX 4090

办公本配置:
CPU:i5-13400
显卡:集成显卡

五、建造者模式的优缺点

优点:

  1. 解耦构建与表示:构建过程(步骤)和产品(结果)分离,同一过程可创建不同产品。
  2. 控制构建过程:指挥者可以严格控制构建步骤,避免无效对象(比如 "没装 CPU 就装内存")。
  3. 灵活扩展:新增产品只需新增具体建造者,无需修改原有代码(符合开闭原则)。
  4. 代码清晰:通过链式调用或分步构建,避免了多参数构造函数的混乱。

缺点:

  1. 类数量增加:每个产品都需要对应具体建造者,若产品复杂且多样,会导致类数量增多。
  2. 适用场景有限:只适合构建 "组成部分相似" 的复杂对象,若产品差异过大(比如电脑和手机),不适合用建造者模式。

六、适用场景

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

  • 构建包含多个组成部分的复杂对象(如电脑、简历、文档)。
  • 需要控制对象构建流程(如必须按顺序设置属性)。
  • 同一构建过程需要生成不同表示(如同一流程组装不同配置的产品)。

常见的实际应用:

  • Java 中的StringBuilder(通过append方法逐步构建字符串)。
  • 很多框架的配置类(如 Spring 的ResourceBuilder)。
  • 建造者模式的简化版(内部 Builder 类)广泛用于 POJO 对象的创建(避免多参数构造函数)。

七、建造者模式 vs 抽象工厂模式

昨天我们讲了抽象工厂模式,它和建造者模式都用于创建对象,但核心区别在于:

  • 抽象工厂模式:关注 "创建一系列相关产品"(如创建电脑的同时创建配套的键盘、鼠标),不关心产品的组装过程。
  • 建造者模式:关注 "一个复杂产品的逐步构建",核心是控制组装步骤,最终产出一个完整对象。

简单说:抽象工厂是 "批量生产相关零件",建造者是 "用零件一步步拼出一个成品"。

总结

建造者模式通过分离 "构建过程" 和 "产品表示",让复杂对象的创建变得清晰、灵活。它特别适合需要精细控制组装步骤、或同一流程需生成不同产品的场景。

如果你的代码中出现了 "参数爆炸" 的构造函数,或需要频繁创建不同组合的复杂对象,不妨试试建造者模式 ------ 它会像一位耐心的工匠,帮你一步步搭建出完美的 "产品"。

相关推荐
一个人的幽默2 小时前
聊一下java获取客户的ip
java
披着羊皮不是狼2 小时前
Spring Boot——从零开始写一个接口:项目构建 + 分层实战
java·spring boot·后端·分层
Deamon Tree3 小时前
【设计题】如何实现限流器
java
短视频矩阵源码定制3 小时前
矩阵系统哪个好?2025年全方位选型指南与品牌深度解析
java·人工智能·矩阵·架构·aigc
kpli903 小时前
Java开发性能优化
java·jvm
三掌柜6663 小时前
C++ 零基础入门与冒泡排序深度实现
java·开发语言·c++
卿言卿语4 小时前
CC23-最长的连续元素序列长度
java·算法·哈希算法
light_forest4 小时前
tcp_connect_v4接口
java·网络·tcp/ip
JIngJaneIL4 小时前
助农惠农服务平台|助农服务系统|基于SprinBoot+vue的助农服务系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·毕设·助农惠农服务平台