当前位置: 首页 > news >正文

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

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

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

一、什么是建造者模式

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

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

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

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

​
// 传统方式:构造函数参数爆炸
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,它包含多个部件:

// 产品:电脑
public class Computer {private String cpu;      // CPUprivate 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. 定义具体建造者

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

​
// 具体建造者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. 定义指挥者

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

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

4. 测试代码

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

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 抽象工厂模式

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

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

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

总结

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

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

http://www.dtcms.com/a/577900.html

相关文章:

  • P3384 【模板】重链剖分/树链剖分
  • OpenCV(二十):位运算
  • 重组蛋白纯化标签科普:从His到SUMO、Avi的全面解析
  • 【QT第三章】常用控件1
  • 鱼台做网站多少钱wordpress 防黑
  • 南通网站建设排名公司网站怎么做图片放映效果
  • AI Agent:突破工作流局限,开启智能决策新时代
  • 自己动手写深度学习框架(神经网络的引入)
  • 西安专业网站建设服务好查询食品注册商标查询官网
  • ref对比reactive
  • 基于融智学双重形式化的汉字汉语数学建模方法
  • 手机wap网站多少钱wordpress页面简码
  • 嘉兴网嘉兴网站建设网址大全汽车之家官方网
  • 基于单片机的智能高温消毒与烘干系统设计
  • vue.js设计与实现(待续)
  • 2025 Vue UI 组件库选型
  • 网站内置字体法治网站的建设整改措施
  • 杭州高端网站设计南宁伯才网络建站如何
  • 面试题001
  • 【C#】NLog配置同时写入网络共享路径与本地路径日志
  • 用通俗易懂 + Android 开发实战的方式,详细讲解 Kotlin Flow 中的 retryWhen 操作符
  • Android 四大组件——BroadcastReceiver(广播)
  • 好看的单页面网站模板免费下载百度知道怎么赚钱
  • HTTP与HTTPS的核心区别及加密流程全解析:从明文传输到安全通信的演进
  • 好大夫王建设在线个人网站第一推广网
  • QML学习笔记(五十三)QML与C++交互:数据转换——序列类型与 JavaScript 数组的转换
  • Spring AI Alibaba语音合成实战:从零开始实现文本转语音功能
  • 科技向善,让养老更有温度——智慧养老的痛点破局与趋势前瞻
  • flink开发遇到的问题
  • “IP 地址” 咋分类?用 “电话号码分区” 讲透 A/B/C 类地址​