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

建造者模式深度解析与实战应用

作者简介

我是摘星,一名全栈开发者,专注 Java后端开发、AI工程化 与 云计算架构 领域,擅长Python技术栈。热衷于探索前沿技术,包括大模型应用、云原生解决方案及自动化工具开发。日常深耕技术实践,乐于分享实战经验与学习心得,希望用通俗易懂的方式帮助开发者快速掌握核心技术。持续输出AI、云计算及开源技术相关内容,欢迎关注交流!

目录

作者简介

1. 技术背景

2. 概念定义

2.1 建造者模式定义

2.2 模式结构图解

3. 原理剖析

3.1 工作流程

3.2 设计原则体现

4. 技术实现

4.1 经典实现(汽车制造示例)

4.2 变体实现(链式调用版)

5. 应用场景

5.1 典型适用场景

5.2 行业应用分布

6. 实际案例

6.1 Java标准库应用

6.2 Spring框架中的BeanDefinitionBuilder

6.3 Lombok的@Builder实现

7. 优缺点分析

7.1 核心优势

7.2 潜在缺点

8. 纵横对比

8.1 建造者 vs 工厂模式

8.2 建造者 vs 抽象工厂

9. 实战思考

9.1 最佳实践建议

9.2 性能优化策略

10. 总结


1. 技术背景

在软件开发中,当遇到需要创建包含多个组成部分的复杂对象时(如HTML文档、汽车配置、订单系统等),传统构造方法面临三大痛点:

  1. 构造函数参数爆炸(Telescoping Constructor)
  2. 对象属性设置不完整(部分构造问题)
  3. 构造过程不可控(无法保证必填字段)

根据GitHub 2023年代码分析统计,建造者模式在以下场景使用率最高:

  • 配置对象构建(占比38%)
  • 文档生成系统(占比25%)
  • 游戏实体创建(占比18%)
  • 测试数据构造(占比12%)

2. 概念定义

2.1 建造者模式定义

建造者模式将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。其核心组件包括:

角色

职责说明

Director

控制构建过程的主管类

Builder

抽象构建接口

ConcreteBuilder

具体构建实现

Product

最终生成的复杂对象

2.2 模式结构图解

图1:建造者模式类图 - 展示主管、构建器与产品的协作关系

3. 原理剖析

3.1 工作流程

图2:建造者模式时序图 - 分步骤构建复杂对象的过程

3.2 设计原则体现

  1. 单一职责原则:将对象构造逻辑与业务逻辑分离
  2. 开闭原则:新增构建方式无需修改既有代码
  3. 控制反转:主管类统一管理构建流程

4. 技术实现

4.1 经典实现(汽车制造示例)

// 产品类  
class Car {  private String engine;  private int wheels;  private String color;  // 设置方法省略...  public void showSpecs() {  System.out.printf("Engine: %s, Wheels: %d, Color: %s\n",  engine, wheels, color);  }  
}  // 抽象建造者  
interface CarBuilder {  void buildEngine();  void buildWheels();  void paintColor();  Car getResult();  
}  // 具体建造者  
class SportsCarBuilder implements CarBuilder {  private Car car = new Car();  @Override  public void buildEngine() {  car.setEngine("V8 Twin-Turbo");  }  @Override  public void buildWheels() {  car.setWheels(4);  }  @Override  public void paintColor() {  car.setColor("Racing Red");  }  @Override  public Car getResult() {  return car;  }  
}  // 主管类  
class Mechanic {  public Car construct(CarBuilder builder) {  builder.buildEngine();  builder.buildWheels();  builder.paintColor();  return builder.getResult();  }  
}  // 客户端调用  
public class Client {  public static void main(String[] args) {  Mechanic mechanic = new Mechanic();  CarBuilder builder = new SportsCarBuilder();  Car myCar = mechanic.construct(builder);  myCar.showSpecs();  }  
}  

4.2 变体实现(链式调用版)

public class User {  private final String firstName;  // 必选  private final String lastName;   // 必选  private final int age;           // 可选  private final String phone;      // 可选  private User(UserBuilder builder) {  this.firstName = builder.firstName;  this.lastName = builder.lastName;  this.age = builder.age;  this.phone = builder.phone;  }  public static class UserBuilder {  private final String firstName;  private final String lastName;  private int age = 0;  private String phone = "";  public UserBuilder(String firstName, String lastName) {  this.firstName = firstName;  this.lastName = lastName;  }  public UserBuilder age(int age) {  this.age = age;  return this;  }  public UserBuilder phone(String phone) {  this.phone = phone;  return this;  }  public User build() {  // 验证必填字段  if (firstName == null || lastName == null) {  throw new IllegalStateException("必填字段缺失");  }  return new User(this);  }  }  
}  // 使用示例  
User user = new User.UserBuilder("张", "三")  .age(30)  .phone("13800138000")  .build();  

5. 应用场景

5.1 典型适用场景

  1. 需要生成的产品对象有复杂内部结构
    • XML/JSON文档生成
    • 邮件报文构造
  1. 产品对象的属性相互依赖
    • 电脑配置(CPU与主板兼容性检查)
    • 订单系统(商品库存验证)
  1. 需要隔离复杂对象的创建和使用
    • 游戏角色创建(装备、技能组合)
    • 测试数据构造

5.2 行业应用分布

图3:行业应用分布图 - 配置管理占据最大比例

6. 实际案例

6.1 Java标准库应用

// StringBuilder就是建造者模式的变体  
String html = new StringBuilder()  .append("<html>")  .append("<head><title>Builder Demo</title></head>")  .append("<body>")  .append("<h1>Hello World</h1>")  .append("</body>")  .append("</html>")  .toString();  

6.2 Spring框架中的BeanDefinitionBuilder

BeanDefinitionBuilder builder = BeanDefinitionBuilder  .rootBeanDefinition(MyService.class)  .addPropertyValue("host", "192.168.1.1")  .setInitMethodName("init")  .setScope(BeanDefinition.SCOPE_SINGLETON);  BeanDefinition beanDefinition = builder.getBeanDefinition();  

6.3 Lombok的@Builder实现

@Builder  
public class Order {  private String orderId;  private List<String> items;  private double totalPrice;  
}  // 自动生成建造者  
Order order = Order.builder()  .orderId("ORD-2023-001")  .items(Arrays.asList("Item1", "Item2"))  .totalPrice(99.99)  .build();  

7. 优缺点分析

7.1 核心优势

  1. 构造过程可控:可以精细化控制构建步骤
  2. 参数灵活组合:避免构造器参数爆炸问题
  3. 产品隔离:隐藏产品内部表示
  4. 构建复用:相同构建过程可创建不同产品

7.2 潜在缺点

  1. 代码复杂度增加:需要额外创建Builder类
  2. 性能开销:相比直接构造略有性能损失
  3. 适用范围有限:简单对象使用反而增加负担

图4:优缺点分析图

8. 纵横对比

8.1 建造者 vs 工厂模式

对比维度

建造者模式

工厂模式

构造目标

多部分组成的复杂对象

单个标准产品

构造过程

分步骤构造

一步构造完成

关注重点

对象的组装过程

对象的创建行为

适用场景

参数可选且组合复杂

固定结构的简单对象

8.2 建造者 vs 抽象工厂

对比维度

建造者模式

抽象工厂模式

产品数量

构建单个复杂对象

创建多个相关对象族

构造方式

分步骤渐进式构建

一次性创建完整产品族

核心目标

控制复杂对象的构造过程

保证产品族的兼容性

9. 实战思考

9.1 最佳实践建议

  1. 必选参数处理:通过Builder构造函数强制传入必选参数
  2. 参数验证时机:在build()方法中进行完整性校验
  3. 不可变对象:配合final字段创建线程安全对象
  4. 组合使用模式
// 建造者+原型模式  
public CarBuilder setPrototype(Car prototype) {  this.car = prototype.clone();  return this;  
}  

9.2 性能优化策略

  1. 对象池技术:对频繁创建的Builder实例进行池化
  2. 缓存构建结果:对相同参数的构建结果进行缓存
  3. 静态工厂方法:简化常用配置的构建过程
public static UserBuilder adminUser() {  return new UserBuilder("admin", "system")  .age(30)  .phone("10086");  
}  

10. 总结

建造者模式作为创建型设计模式的重要成员:

  1. 有效解决了复杂对象构造的参数组合与流程控制问题
  2. 通过分步构建机制,实现了构造过程与产品表示的分离
  3. 在JDK、Spring等主流框架中广泛应用,特别适合配置管理和文档生成场景
  4. 现代开发中常与Lombok等工具结合,大幅减少样板代码

随着领域驱动设计(DDD)的普及,建造者模式在值对象构建聚合根创建领域展现出新的价值。当系统需要处理具有复杂构造逻辑的业务对象时,它仍然是不可替代的解决方案。

权威参考:

  1. Effective Java - Item 2: Builder Pattern(Joshua Bloch经典论述)
  2. Builder Pattern in Spring Framework(官方文档)
  3. Lombok @Builder Annotation(自动化实现方案)
  4. Refactoring.Guru: Builder Pattern(模式详解与互动案例)

相关文章:

建造者模式深度解析与实战应用

作者简介 我是摘星&#xff0c;一名全栈开发者&#xff0c;专注 Java后端开发、AI工程化 与 云计算架构 领域&#xff0c;擅长Python技术栈。热衷于探索前沿技术&#xff0c;包括大模型应用、云原生解决方案及自动化工具开发。日常深耕技术实践&#xff0c;乐于分享实战经验与…...

代码中文抽取工具并替换工具(以ts为例)

文章目录 基本思路目录结构配置文件AST解析替换代码中文生成Excel启动脚本 基本思路 通过对应语言的AST解析出中文相关信息&#xff08;文件、所在行列等&#xff09;存到临时文件通过相关信息&#xff0c;逐个文件位置替换掉中文基于临时文件&#xff0c;通过py脚本生成Excel…...

pgsql batch insert optimization (reWriteBatchedInserts )

reWriteBatchedInserts 是 PostgreSQL JDBC 驱动 提供的一个优化选项&#xff0c;它可以 重写批量插入语句&#xff0c;从而提高插入性能。 作用 当 reWriteBatchedInsertstrue 时&#xff0c;PostgreSQL JDBC 驱动会将 多个单独的 INSERT 语句 转换为 一个多行 INSERT 语句&a…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(上)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

华为云Flexus+DeepSeek征文 | 基于DeepSeek-V3构建企业知识库问答机器人实战

作者简介 我是摘星&#xff0c;一名专注于云计算和AI技术的开发者。本次通过华为云MaaS平台体验DeepSeek系列模型&#xff0c;将实际使用经验分享给大家&#xff0c;希望能帮助开发者快速掌握华为云AI服务的核心能力。 目录 作者简介 1. 引言 2. 技术选型与架构设计 2.1 技…...

【Docker 01】Docker 简介

&#x1f308; 一、虚拟化、容器化 ⭐ 1. 什么是虚拟化、容器化 物理机&#xff1a;真实存在的服务器 / 计算机&#xff0c;对于虚拟机来说&#xff0c;物理机为虚拟机提供了硬件环境。虚拟化&#xff1a;通过虚拟化技术将一台计算机虚拟为 1 ~ n 台逻辑计算机。在一台计算机…...

信息最大化(Information Maximization)

信息最大化在目标域无标签的域自适应任务中&#xff0c;它迫使模型在没有真实标签的情况下&#xff0c;对未标记数据产生高置信度且类别均衡的预测。此外&#xff0c;这些预测也可以作为伪标签用于自训练。 例如&#xff0c;在目标域没有标签时&#xff0c;信息最大化损失可以…...

整数的字典序怎么算

在Python中&#xff0c;字典序&#xff08;lexicographical order&#xff09;通常指的是按照字符串的字典顺序进行比较或排序。对于整数来说&#xff0c;字典序可以理解为将整数转换为字符串后进行比较的顺序。 计算整数的字典序 要计算整数的字典序&#xff0c;可以按照以下…...

知识拓展卡————————关于Access、Trunk、Hybrid端口

目录 什么是Trunk List、VLAN ID、PVID&#xff1a; VLAN ID&#xff08;Virtual Local Area Network Identifier&#xff09;&#xff1a; Trunk List&#xff08;Trunk列表&#xff09;&#xff1a; PVID&#xff08;Prot VLAN ID&#xff09;: 关于Native VLAN &#x…...

AUTOSAR实战教程--DoIP_02_诊断链路建立流程

第一步&#xff1a;DoIP实体车辆声明/诊断仪车辆识别请求 打开激活线以后&#xff0c;DoIP实体发的三帧车辆声明报文。其中包含了DoIP实体的诊断逻辑地址&#xff08;可以类比DoCAN的物理请求/响应地址&#xff09;&#xff0c;对应车辆的VIN码&#xff08;若已配置&#xff0…...

音频剪辑软件少之又少好用

我们平时见到的图片以及视频编辑工具非常多&#xff0c;但是音频剪辑软件却是少之又少&#xff0c;更不用说有没有好用的&#xff0c;今天&#xff0c;给大家带来一款非常专业的音频剪辑软件&#xff0c;而且是会员喔。 软件简介 一款手机号登录即可以享受会员的超专业音频剪…...

客户端和服务器已成功建立 TCP 连接【输出解析】

文章目录 图片**1. 连接状态解析****第一条记录&#xff08;服务器监听&#xff09;****第二条记录&#xff08;客户端 → 服务器&#xff09;****第三条记录&#xff08;服务器 → 客户端&#xff09;** **2. 关键概念澄清****(1) 0.0.0.0 的含义****(2) 端口号的分配规则** *…...

多标签多分类 用什么函数激活

在多标签多分类任务中&#xff0c;激活函数的选择需要根据任务特性和输出层的设计来决定。以下是常见的激活函数及其适用场景&#xff1a; 一、多标签分类任务的特点 每个样本可以属于多个类别&#xff08;标签之间非互斥&#xff0c;例如一篇文章可能同时属于 “科技” 和 “…...

day26-计算机网络-4

1. tcp的11种状态 ss -ant -a 表示看所有状态 -n 表示不将ip解析为主机名 -t 表示tcp 1.1. closed状态&#xff08;客户端、服务端&#xff09; 客户端发起建立连接前的状态服务端启动服务前的状态 1.2. listen状态&#xff08;服务端&#xff09; 服务端软件运行的时候状…...

ngx_stream_geo_module在传输层实现高性能 IP Region 路由

一、模块定位与核心价值 层次&#xff1a;工作在 Stream (TCP/UDP) 层&#xff0c;和 ngx_http_geo_module 的 L7 语义互补。作用&#xff1a;基于客户端 IP 前缀 / 范围生成一个 Nginx 变量&#xff0c;可在后续 proxy_pass、map、limit_conn、access 等指令中使用&#xff0…...

国防科技大学计算机基础慕课课堂学习笔记

1.信息论 香农作为信息论的这个创始人&#xff0c;给出来了这个信息熵的计算方法&#xff0c;为我们现在的这个生活的很多领域奠定了基础&#xff0c;我第一次听说这个信息熵是在这个数学建模里面的理论学习中有关于这个&#xff1a;决策树的模型&#xff0c;在那个问题里面&a…...

【第七篇】 SpringBoot项目的热部署

简介 本文介绍了热部署&#xff08;Hot Deployment&#xff09;的概念、使用场景及在IDEA中的配置方法。热部署可在不重启应用的情况下动态更新代码&#xff0c;提升开发效率&#xff0c;适用于调试、微服务架构和自动化测试等场景。文章详细说明了热部署的实现步骤&#xff08…...

解决pycharm同一个文件夹下from *** import***仍显示No module named

1、&#xff0c;from ***import *&#xff0c;同文件夹中已有.py文件但是仍然报错No module named 原因是因为pycharm没有把文件夹设置为根目录&#xff0c;只需要在文件夹的上一级设置为根目录即可&#xff0c;测试过如果仅仅将当前的文件夹设置仍然报错&#xff0c;如果把最上…...

GO 基础语法和数据类型面试题及参考答案(上)

目录 Go 中变量定义方式有哪些&#xff1f;各有什么适用场景&#xff1f; 使用 : 定义变量的限制是什么&#xff1f; 全局变量可以使用 : 声明吗&#xff1f;为什么&#xff1f; Go 中如何声明一个多变量赋值&#xff1f;有哪些注意事项&#xff1f; 常量能否通过表达式赋值…...

使用 Redisson 实现分布式锁—解决方案详解

Redisson 是 Redis 官方推荐的 Java 客户端&#xff0c;提供了一系列分布式服务实现&#xff0c;其中分布式锁是其核心功能之一。本文将深入解析 Redisson 分布式锁的实现原理、高级特性和最佳实践。 一、Redisson 分布式锁的优势 与传统实现的对比 特性手动实现Redisson 实现…...

结合三维基因建模与智能体技术打造工业软件无码平台

通过深度整合 Protocol Buffers (Protobuf)、gRPC 及 Microsoft AI 技术&#xff0c;构建面向智能制造的高性能、智能化 PLM 平台。 一、Protocol Buffers 深度集成 1. 基因模型标准化定义 三维基因容器 Protobuf 规范&#xff1a; protobuf syntax "proto3"; pa…...

Python Day46

Task&#xff1a; 1.不同CNN层的特征图&#xff1a;不同通道的特征图 2.什么是注意力&#xff1a;注意力家族&#xff0c;类似于动物园&#xff0c;都是不同的模块&#xff0c;好不好试了才知道。 3.通道注意力&#xff1a;模型的定义和插入的位置 4.通道注意力后的特征图和热力…...

基于PostGIS的各地级市路网长度统计及Echarts图表可视化实践-以湖南省为例

目录 前言 一、路网长度计算 1、地级市列表查询 2、地级市路网长度查询 二、Echarts可视化实现 1、Echarts后端生成 2、引入Colormap配色 3、前端微调 三、总结 前言 在当今快速发展的社会中&#xff0c;交通路网的建设与布局对于一个地区的经济发展、居民生活以及城市…...

mac版excel如何制作时长版环形图

设置辅助列 创建簇状柱形图 将辅助列绘制在次坐标轴 工作时长在主坐标轴&#xff0c;右键分别更改图表类型为圆环。 辅助列圆环全部为灰色&#xff0c;边框为白色 辅助列设置透明度100% 设置辅助列和工作时长列同样的圆环大小 可得 核心&#xff1a;只要辅助列边框不透明…...

PCB设计教程【大师篇】——STM32开发板原理图设计(电源部分)

前言 本教程基于B站Expert电子实验室的PCB设计教学的整理&#xff0c;为个人学习记录&#xff0c;旨在帮助PCB设计新手入门。所有内容仅作学习交流使用&#xff0c;无任何商业目的。若涉及侵权&#xff0c;请随时联系&#xff0c;将会立即处理 目录 前言 1. 工程创建与前期…...

k8s4部署

configMap configmap概述&#xff1a;数据会存储在etcd数据库&#xff0c;其应用场景主要在应用程序的配置 configmap支持的类型&#xff08;1&#xff09;键值对&#xff08;2&#xff09;多行数据 pod使用configmap资源有两种常见的方式&#xff08;1&#xff09;变量注入&a…...

贝叶斯医学分析中“先验”的如何进行选择(文献解读)

贝叶斯医学分析中“先验”的如何进行选择&#xff08;文献解读&#xff09; 作者&#xff1a;Callum Taylor, Kathryn Puxty, Tara Quasim, Martin Shaw 文章标题&#xff1a;Understanding Bayesian analysis of clinical trials: an overview for clinicians 期刊名称&#x…...

【汇编逆向系列】七、函数调用包含多个参数之浮点型- XMM0-3寄存器

目录 1. 汇编代码 1.1 debug编译 1.2 release编译 2. 汇编分析 2.1 浮点参数传递规则 2.2 栈帧rsp的变化时序 2.3 参数的访问逻辑 2.4 返回值XMM0寄存器 3. 汇编转化 3.1 Debug编译 3.2 Release 编译 3.3 C语言转化 1. 汇编代码 上一节介绍了整型的函数传参&#x…...

【MySQL系列】MySQL 执行 SQL 文件

博客目录 一、MySQL 执行 SQL 文件的常见场景二、MySQL 执行 SQL 文件的主要方法1. 使用 MySQL 命令行客户端2. 在 MySQL 交互界面中使用 source 命令3. 使用 MySQL Workbench 等图形化工具4. 使用编程语言接口 三、执行 SQL 文件时的注意事项1. 字符集问题2. 事务处理3. 错误处…...

论文MR-SVD

每个像素 7 个 FLOPs意思&#xff1a; FLOPs&#xff08;浮点运算次数&#xff09;&#xff1a;衡量算法计算复杂度的指标&#xff0c;数值越小表示运算越高效。含义&#xff1a;对图像中每个像素进行处理时&#xff0c;仅需执行7 次浮点运算&#xff08;如加减乘除等&#xf…...