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

【设计模式】【创建型模式】建造者模式(Builder)

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD
🔥 2025本人正在沉淀中… 博客更新速度++
👍 欢迎点赞、收藏、关注,跟上我的更新节奏
🎵 当你的天空突然下了大雨,那是我在为你炸乌云

文章目录

  • 一、入门
    • 什么是建造者模式?
    • 为什么要建造者模式?
    • 如何实现建造者模式?
      • 传统建造者
      • 链式建造者
  • 二、建造者模式在框架源码中的运用
    • Java中的StringBuilder和StringBuffer
    • Spring Framework中的BeanDefinitionBuilder
  • 三、总结
    • 建造者模式的优点
    • 建造者模式的缺点
    • 建造者模式的适用场景

一、入门

什么是建造者模式?

建造者模式(Builder Pattern)是一种创建型设计模式,用于逐步构建复杂对象。
它通过将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。

为什么要建造者模式?

假设我们要组装电脑,需要cpu、内存、硬盘、gpu、电源…
没有使用建造者模式,我们会这样写:

public class Computer {private String cpu;private String memory;private String hardDisk;private String gpu;private String powerSupply;public Computer(String cpu, String memory, String hardDisk, String gpu, String powerSupply) {this.cpu = cpu;this.memory = memory;this.hardDisk = hardDisk;this.gpu = gpu;this.powerSupply = powerSupply;}
}

存在问题

  1. 构造方法参数过多(Telescoping Constructor Problem):调用这样的构造方法时,代码会变得非常冗长且难以理解:
Computer computer = new Computer("Intel i7", "16GB", "1TB SSD", "NVIDIA RTX 3080", "750W");
  1. 对象的不一致性:在某些情况下,对象可能需要在不同的步骤中逐步构建。如果没有建造者模式,对象可能会在未完全初始化的情况下被使用,导致不一致的状态。
  2. 代码的可读性可维护性变差:当对象的构建过程复杂时,直接在客户端代码中编写构建逻辑会导致代码重复和难以维护。
Computer computer = new Computer();
computer.setCpu("Intel i7");
computer.setMemory("16GB");
computer.setHardDisk("1TB SSD");
computer.setGpu("NVIDIA RTX 3080");
computer.setPowerSupply("750W");
  1. 缺乏灵活性:如果对象的构建过程需要支持多种不同的配置或表示形式,直接在客户端代码中编写构建逻辑会导致代码的灵活性降低。例如,如果需要构建不同类型的计算机(如游戏计算机、办公计算机等),每种类型的构建逻辑可能会有所不同,导致代码重复和难以扩展。

如何实现建造者模式?

传统建造者

主要角色

  1. Product(产品类):最终要构建的复杂对象。
  2. Builder(抽象建造者):定义构建步骤的接口。
  3. ConcreteBuilder(具体建造者):实现Builder接口,提供具体的构建步骤。
  4. Director(指挥者):负责调用Builder的步骤,控制构建过程。

【案例】组装电脑 - 改
在这里插入图片描述
Product(产品类)Computer类,最终要构建的复杂对象。

class Computer {private String cpu;private String memory;private String hardDisk;public void setCpu(String cpu) {this.cpu = cpu;}public void setMemory(String memory) {this.memory = memory;}public void setHardDisk(String hardDisk) {this.hardDisk = hardDisk;}@Overridepublic String toString() {return "Computer [cpu=" + cpu + ", memory=" + memory + ", hardDisk=" + hardDisk + "]";}
}

Builder(抽象建造者)ComputerBuilder接口,定义构建步骤的接口。

interface ComputerBuilder {void buildCpu();void buildMemory();void buildHardDisk();Computer getComputer();
}

ConcreteBuilder(具体建造者)GamingComputerBuilder类,实现Builder接口,提供具体的构建步骤。

class GamingComputerBuilder implements ComputerBuilder {private Computer computer;public GamingComputerBuilder() {this.computer = new Computer();}@Overridepublic void buildCpu() {computer.setCpu("Intel i7");}@Overridepublic void buildMemory() {computer.setMemory("16GB");}@Overridepublic void buildHardDisk() {computer.setHardDisk("1TB SSD");}@Overridepublic Computer getComputer() {return computer;}
}

Director(指挥者)ComputerDirector类,负责调用Builder的步骤,控制构建过程。

class ComputerDirector {private ComputerBuilder computerBuilder;public ComputerDirector(ComputerBuilder computerBuilder) {this.computerBuilder = computerBuilder;}public void constructComputer() {computerBuilder.buildCpu();computerBuilder.buildMemory();computerBuilder.buildHardDisk();}public Computer getComputer() {return computerBuilder.getComputer();}
}

客户端代码

public class BuilderPatternDemo {public static void main(String[] args) {ComputerBuilder builder = new GamingComputerBuilder();ComputerDirector director = new ComputerDirector(builder);director.constructComputer();Computer computer = director.getComputer();System.out.println(computer);}
}

链式建造者

流式接口(Fluent Interface)或链式建造者模式。这种方式通过返回this来实现链式调用,代码更加简洁和直观。
下面是一个使用链式调用的建造者模式示例:

产品类(Computer)

class Computer {private String cpu;private String memory;private String hardDisk;private String gpu;public void setCpu(String cpu) {this.cpu = cpu;}public void setMemory(String memory) {this.memory = memory;}public void setHardDisk(String hardDisk) {this.hardDisk = hardDisk;}public void setGpu(String gpu) {this.gpu = gpu;}@Overridepublic String toString() {return "Computer [cpu=" + cpu + ", memory=" + memory + ", hardDisk=" + hardDisk + ", gpu=" + gpu + "]";}
}

建造者类(ComputerBuilder)

class ComputerBuilder {private Computer computer;public ComputerBuilder() {this.computer = new Computer();}public ComputerBuilder buildCpu(String cpu) {computer.setCpu(cpu);return this; // 返回this,支持链式调用}public ComputerBuilder buildMemory(String memory) {computer.setMemory(memory);return this; // 返回this,支持链式调用}public ComputerBuilder buildHardDisk(String hardDisk) {computer.setHardDisk(hardDisk);return this; // 返回this,支持链式调用}public ComputerBuilder buildGpu(String gpu) {computer.setGpu(gpu);return this; // 返回this,支持链式调用}public Computer build() {return computer; // 返回最终构建的对象}
}

客户端代码

public class BuilderPatternDemo {public static void main(String[] args) {// 使用链式调用构建对象Computer computer = new ComputerBuilder().buildCpu("Intel i7").buildMemory("16GB").buildHardDisk("1TB SSD").buildGpu("NVIDIA RTX 3080").build();System.out.println(computer);}
}

对比传统建造者模式

  • 传统建造者模式:通过Director类控制构建过程,适合构建过程固定的场景。
  • 链式建造者模式:通过返回this实现链式调用,适合构建过程灵活、需要动态配置的场景。

二、建造者模式在框架源码中的运用

Java中的StringBuilder和StringBuffer

StringBuilderStringBuffer是Java中用于构建字符串的类,它们使用了类似建造者模式的思想,通过链式调用来逐步构建字符串。
示例

StringBuilder builder = new StringBuilder();
builder.append("Hello").append(" ").append("World");
String result = builder.toString();
System.out.println(result); // 输出: Hello World
  • 分析:
    • append方法返回this,支持链式调用。
    • 通过逐步构建字符串,最终调用toString方法生成结果。

Spring Framework中的BeanDefinitionBuilder

在Spring框架中,BeanDefinitionBuilder用于构建BeanDefinition对象,它是Spring IoC容器中定义Bean的核心类。
示例

BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(MyBean.class);
builder.addPropertyValue("name", "MyBeanName").addPropertyValue("age", 30).setScope(BeanDefinition.SCOPE_SINGLETON);BeanDefinition beanDefinition = builder.getBeanDefinition();
  • 分析:
    • BeanDefinitionBuilder通过链式调用逐步配置Bean的属性。
    • 最终通过getBeanDefinition方法生成BeanDefinition对象。

三、总结

建造者模式的优点

  1. 分离构建与表示
    • 将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。
    • 客户端不需要知道对象的具体构建细节。
  2. 灵活性和可扩展性
    • 可以逐步构建对象,支持动态配置。
    • 新增构建步骤或修改构建顺序非常方便。
  3. 代码可读性和可维护性
    • 链式调用(Fluent Interface)使代码更加简洁和直观。
    • 将复杂的构建逻辑封装在建造者类中,客户端代码更清晰。
  4. 避免构造方法参数过多
    • 通过逐步设置属性,避免了构造方法参数过长的问题(Telescoping Constructor Problem)。
  5. 保证对象的一致性
    • 对象在完全构建之前不会被使用,确保对象的一致性和完整性。

建造者模式的缺点

  1. 增加代码复杂性
    • 需要额外定义建造者类,增加了类的数量。
    • 对于简单对象,使用建造者模式可能会显得冗余。
  2. 适用范围有限
    • 适用于构建复杂对象,如果对象属性较少或构建过程简单,使用建造者模式可能会过度设计。
  3. 性能开销
    • 由于需要创建建造者对象,可能会引入额外的性能开销(通常可以忽略不计)。

建造者模式的适用场景

  1. 构建复杂对象
    • 当对象有很多属性,且构建过程复杂时,适合使用建造者模式。
    • 例如,构建一个包含多个配置项的计算机对象。
  2. 需要多种表示形式
    • 当同一个构建过程需要生成不同的对象表示时,适合使用建造者模式。
    • 例如,构建不同类型的计算机(游戏计算机、办公计算机等)。
  3. 避免构造方法参数过多
    • 当构造方法参数过多,导致代码难以阅读和维护时,适合使用建造者模式。
  4. 需要逐步构建对象
    • 当对象的构建过程需要分步骤完成时,适合使用建造者模式。
    • 例如,构建一个HTTP请求配置对象。
  5. 框架或工具类中的配置对象
    • 在框架或工具类中,经常需要构建复杂的配置对象,建造者模式非常适合这种场景。
    • 例如,Spring中的BeanDefinitionBuilder、Apache HttpClient中的RequestConfig.Builder等。

相关文章:

【设计模式】【创建型模式】建造者模式(Builder)

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD 🔥 2025本人正在沉淀中… 博客更新速度 👍 欢迎点赞、收藏、关注,跟上我的更新节奏 🎵 当你的天空突…...

如何利用国内镜像从huggingface上下载项目

1、利用镜像快速下载项目 在huggingface上下载模型时速度太慢,可以用下面的方法 pip install -U huggingface_hub pip install huggingface-cliexport HF_ENDPOINThttps://hf-mirror.comhuggingface-cli download --resume-download shenzhi-wang/Llama3-8B-Chine…...

pandas常用操作

pandas是Python中用于数据操作和分析的强大库。以下是一些常用的操作: ### 1. 读取数据 - **从CSV文件读取**: python import pandas as pd df pd.read_csv(path/to/file.csv) - **从Excel文件读取**: python df pd.read_exc…...

linux使用

文章目录 前言操作系统的作用组成二、安装linux系统安装VMware Workstation安装ubuntu图形化,命令行finalshell快照目录理解命令执行命令格式常用命令lscdmkdir 前言 本文讲解认识与使用linux操作系统 操作系统的作用 操作系统是用户和计算机的桥梁。比如我们输入…...

基于豆瓣2025电影数据可视化分析系统的设计与实现

✔️本项目旨在通过对豆瓣电影数据进行综合分析与可视化展示,构建一个基于Python的大数据可视化系统。通过数据爬取收集、清洗、分析豆瓣电影数据,我们提供了一个全面的电影信息平台,为用户提供深入了解电影产业趋势、影片评价与演员表现的工…...

基于Python的深度学习音乐推荐系统(有配套论文)

音乐推荐系统 提供实时音乐推荐功能,根据用户行为和偏好动态调整推荐内容 Python、Django、深度学习、卷积神经网络 、算法 数据库:MySQL 系统包含角色:管理员、用户 管理员功能:用户管理、系统设置、音乐管理、音乐推荐管理、系…...

远程计算机无conda情况下配置python虚拟环境

1. 按照正常流程,根据远程计算机的IP地址/用户名/密码,通过pycharm进行部署 部署流程为: pycharm主菜单--> 工具-->部署 -->配置 **注意,pycharm的远程部署必须是专业版 2. 配置远程python解释器 上图是配置SSH解释器的截图&…...

强化学习-价值学习算法

Sarsa 理论解释 Sarsa是基于时序差分算法的,它的公式非常简单且易理解,不像策略梯度算法那样需要复杂的推导过程。 Sarsa的核心函数是 Q ( s , a ) Q(s, a) Q(s,a),它的含义是在状态 s s s下执行 a a a,在后续轨迹中获取的期望…...

Golang深度学习

前言 在2009年,Google公司发布了一种新的编程语言,名为Go(或称为Golang),旨在提高编程效率、简化并发编程,并提供强大的标准库支持。Go语言的设计者们希望通过Go语言能够解决软件开发中的一些长期存在的问…...

基于推荐算法的在线课程推荐系统设计与实现

开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...

es和kibana安装

es安装 安装 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.17.1-linux-x86_64.tar.gz 参考: https://www.cnblogs.com/shamo89/p/18504053 https://blog.csdn.net/u012899618/article/details/130383429 解压 tar -zxvf elastic…...

本地部署Anything LLM+Ollama+DeepSeek R1打造AI智能知识库教程

文章目录 前言1. 本地部署OllamaDeepSeek2. 本地安装Anything LLM3. 配置与使用演示4. 远程调用大模型5. 安装内网穿透6. 配置固定公网地址 前言 本文主要介绍如何在Windows电脑上本地部署Ollama并接入DeepSeek R1大模型,然后使用强大的开源AI工具Anything LLM结合…...

zyNo.25

SSRF漏洞 在了解ssrf漏洞前先了解curl命令的使用 1.curl命令的使用 基本格式&#xff1a;curl<参数值>请求地址 get请求&#xff1a;curl http://127.0.0.1 post请求&#xff1a;curl -X POST -d "a1&b2" http://127.0.0.1/(其中&#xff0c;使用-X参…...

Spring框架基本使用(Maven详解)

前言&#xff1a; 当我们创建项目的时候&#xff0c;第一步少不了搭建环境的相关准备工作。 那么如果想让我们的项目做起来方便快捷&#xff0c;应该引入更多的管理工具&#xff0c;帮我们管理。 Maven的出现帮我们大大解决了管理的难题&#xff01;&#xff01; Maven&#xf…...

关于前后端分离跨域问题——使用DeepSeek分析查错

我前端使用ant design vue pro框架&#xff0c;后端使用kratos框架开发。因为之前也解决过跨域问题&#xff0c;正常是在后端的http请求中加入中间件&#xff0c;设置跨域需要通过的字段即可&#xff0c;代码如下所示&#xff1a; func NewHTTPServer(c *conf.Server, s *conf…...

三层渗透测试-DMZ区域 二三层设备区域

DMZ区域渗透 信息收集 首先先进行信息收集&#xff0c;这里我们可以选择多种的信息收集方式&#xff0c;例如nmap如此之类的&#xff0c;我的建议是&#xff0c;可以通过自己现有的手里小工具&#xff0c;例如无影&#xff0c;密探这种工具&#xff0c;进行一个信息收集。以免…...

领航Linux UDP:构建高效网络新纪元

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 引言Udp和Tcp的异同相同点不同点总结 1.1、socket1.2、bind1.3、recvfrom1.4、sendto2.1、代码2.1、说明3.1、代码3.2、说明 引言 在前几篇博客中&#xff0c;我们学习了Linux网络编程中的一些概念。…...

基于MATLAB的均匀面阵MUSIC算法DOA估计仿真

基于MATLAB的均匀面阵MUSIC算法DOA估计仿真 文章目录 前言一、二维MUSIC算法原理二、二维MUSIC算法MATLAB仿真三、MATLAB源代码总结 前言 \;\;\;\;\; 在波达角估计算法中&#xff0c;MUSIC 算法与ESPRIT算法属于特征结构子空间算法&#xff0c;是波达角估计算法中的基石。在前面…...

HTML/CSS中后代选择器

1.作用:选中指定元素中,符合要求的后代元素. 2.语法:选择器1 选择器2 选择器3 ...... 选择器n(使用空格隔开) 3.举例: /* 选中ul中的所有li */ul li{color: red;}/* 选中类名为subject元素中的所有li */.subject li{color: blue;}/* 选中类名为subject元素中的所有类名为f…...

深入解析「卡顿帧堆栈」 | UWA GPM 2.0 技术细节与常见问题

在游戏开发过程中&#xff0c;卡顿问题一直是影响玩家体验的关键因素。UWA GPM 2.0全新推出的「卡顿帧堆栈」功能&#xff0c;专为研发团队提供精准、高效的卡顿分析方案&#xff0c;能够直观呈现游戏运行时的堆栈信息&#xff0c;助力团队迅速找到性能瓶颈。该功能一经上线&am…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

如何应对敏捷转型中的团队阻力

应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中&#xff0c;明确沟通敏捷转型目的尤为关键&#xff0c;团队成员只有清晰理解转型背后的原因和利益&#xff0c;才能降低对变化的…...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...

JS红宝书笔记 - 3.3 变量

要定义变量&#xff0c;可以使用var操作符&#xff0c;后跟变量名 ES实现变量初始化&#xff0c;因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符&#xff0c;可以创建一个全局变量 如果需要定义…...