设计模式(创建型)-建造者模式

news2025/3/31 9:48:07

定义

        建造者模式(Builder Pattern)是一种创建型设计模式,它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。该模式允许通过多个简单的步骤逐步构建出一个复杂的对象,用户只需指定复杂对象的类型和内容,而无需了解内部具体的构建细节。

类图

角色

        建造者模式包含四个主要角色,其类图结构如下:​

  1. 产品角色(Product):包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。例如,一个房屋对象,它可能包含墙体、屋顶、门窗等部件。​

  2. 抽象建造者(Builder):定义了创建产品各个子部件的抽象方法接口,通常还包含一个返回复杂产品的方法 getResult()。例如,定义一个建造房屋的抽象接口,其中包含创建墙体、屋顶、门窗等抽象方法。​

  3. 具体建造者(Concrete Builder):实现抽象建造者接口,完成复杂产品各个部件的具体创建方法。例如,实现建造普通房屋的具体建造者类,实现抽象接口中创建墙体、屋顶、门窗等具体逻辑。​

  4. 指挥者(Director):调用建造者对象中的部件构造与装配方法完成复杂对象的创建,指挥者中不涉及具体产品的信息。例如,一个房屋建造指挥者,它调用建造者对象的方法,按照一定顺序构建房屋。

优缺点

优点​

  • 封装性好,构建和表示分离:将复杂对象的构建过程封装在建造者类中,客户端只需要关心如何使用建造者创建对象,而无需了解对象内部的构建细节,使得代码的耦合度降低,维护性提高。​

  • 拓展性好:各个具体的建造者相互独立,增加新的具体建造者无需修改原有类库的代码,符合 “开闭原则”。例如,如果需要增加一种新类型的房屋建造,只需要新增一个具体建造者类实现抽象建造者接口即可,不会影响到其他部分的代码。​

  • 便于控制细节风险:客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其他模块产生任何影响。例如,在建造房屋时,建造者可以根据实际情况对墙体的厚度、屋顶的材质等细节进行调整,而不会影响到房屋的整体结构和其他部分的构建。​

缺点​

  • 产品的组成部分必须相同,限制适用范围:该模式要求产品的组成部分相对固定,如果产品的结构和组成经常变化,使用建造者模式可能不太合适。例如,如果房屋的基本组成部分(如墙体、屋顶、门窗)经常变动,那么使用建造者模式就需要频繁修改各个建造者类和相关的代码,维护成本较高。​

  • 后期维护成本较大:如果产品的内部变化复杂,产品内部发生变化时,建造者也要同步修改。例如,当房屋的结构发生重大变化,如从传统的砖混结构变为框架结构时,所有的具体建造者类都需要相应地修改创建部件的方法,这可能会涉及到大量的代码修改和测试工作。

建造者模式和工厂模式比较

        建造者模式和工厂模式都属于创建型设计模式,但它们的关注点不同:​

  • 建造者模式注重零部件的组装过程:强调通过一步步的构建过程来创建复杂对象,将对象的构建和表示分离,更侧重于描述如何将多个简单部件组合成一个复杂对象。例如,建造房屋时,关注墙体、屋顶、门窗等部件如何按照一定顺序组装成一个完整的房屋。​

  • 工厂模式更注重零部件的创建过程:主要用于创建对象,它提供了一种创建对象的方式,将对象的创建和使用分离,重点在于根据不同的条件创建不同类型的对象。例如,工厂模式可以根据客户需求创建不同类型的汽车,而不关注汽车内部零部件的组装过程。​

        在实际应用中,两者可以结合使用。例如,在生产汽车时,工厂模式负责创建汽车的各个零部件(如发动机、轮胎等),而建造者模式负责将这些零部件组装成一辆完整的汽车。

使用场景

创建复杂对象结构​

        当需要创建的对象是由多个部件构成,且这些部件的组合方式多样时,建造者模式能派上大用场。以电商平台为例,订单对象的创建过程颇为复杂,订单包含用户信息、收货地址、商品列表、促销优惠、支付方式等多个部件。利用建造者模式,可将订单的构建过程进行拆分,让具体建造者分别负责构建各个部件,指挥者按照既定的业务逻辑,将这些部件组合成完整的订单对象。这样一来,不仅创建订单的逻辑更加清晰,后续若要新增或修改订单的某个部件,只需调整相应的建造者类,不会对整体的订单创建流程造成过大影响。​

用户交互与配置生成​

        在交互式应用程序中,用户通常会通过界面设置各种参数来生成特定的对象。以游戏开发为例,玩家在创建游戏角色时,需要对角色的种族、职业、外貌、技能等多项属性进行配置。运用建造者模式,可为每种角色类型创建对应的具体建造者,玩家通过界面输入配置信息,指挥者依据这些信息调用相应的建造者方法,构建出符合玩家需求的游戏角色。这种方式将角色创建的复杂逻辑封装在建造者和指挥者中,使得用户界面与角色创建逻辑解耦,提升了代码的可维护性和扩展性。​

分步骤创建和延迟创建​

        在某些场景下,对象的创建并非一蹴而就,可能需要分多个步骤完成,或者根据特定条件延迟创建对象的某些部分。以报表生成系统为例,报表对象可能包含数据表格、图表、文字说明等多个部分。借助建造者模式,可以先创建报表的基本结构,然后根据用户的请求逐步生成数据表格、图表等内容。当数据量较大时,还能通过延迟创建的方式,避免在系统启动时就进行大量的数据加载和报表生成操作,提升系统的响应速度和性能。​

多平台适配​

        当需要为不同的平台或环境创建对象时,建造者模式同样适用。以移动应用开发为例,应用可能需要针对 iOS 和 Android 平台生成不同风格的界面布局。通过创建不同平台对应的具体建造者,分别负责生成适用于各自平台的界面元素,指挥者则根据运行平台调用相应的建造者,创建出符合平台特性的界面。这种方式将平台相关的代码封装在具体建造者中,便于对不同平台的界面进行独立维护和更新。​

构建链式操作对象​

        在一些流式 API 的设计中,常常会使用建造者模式来实现链式操作。以 Java 的Stream API 为例,通过链式调用各种方法,可以对数据进行筛选、映射、排序等一系列操作。建造者模式通过链式调用的方式,将多个操作步骤串联起来,使代码更加简洁和可读。用户只需关注每个操作的逻辑,而无需关心对象的创建和组装过程,极大地提升了代码的开发效率。

使用案例

Java  StringBuilder

        在 Java 中,StringBuilder 类的使用类似于建造者模式。StringBuilder 用于创建可变的字符串对象,它提供了一系列方法来逐步构建字符串。

1. 类比建造者模式的角色:

  • StringBuilder 类可以看作是具体建造者,它实现了构建字符串的具体方法。例如,append() 方法用于将各种类型的数据追加到字符串中,类似于具体建造者创建产品部件的方法。​

  • StringBuilder 类中的 toString() 方法可以类比为抽象建造者中的 getResult() 方法,用于返回最终构建好的字符串对象(产品)。

2. 使用示例:

StringBuilder sb = new StringBuilder();

sb.append("Hello");

sb.append(", ");

sb.append("World!");

String result = sb.toString();

System.out.println(result);

        通过 StringBuilder 的 append() 方法逐步构建字符串,最后通过 toString() 方法得到完整的字符串,体现了建造者模式逐步构建复杂对象的思想。虽然 StringBuilder 并不是严格意义上的建造者模式实现,但它的设计思路和使用方式与建造者模式有相似之处,帮助我们更好地理解和运用建造者模式的概念。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2323254.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git 之配置ssh

1、打开 Git Bash 终端 2、设置用户名 git config --global user.name tom3、生成公钥 ssh-keygen -t rsa4、查看公钥 cat ~/.ssh/id_rsa.pub5、将查看到的公钥添加到不同Git平台 6、验证ssh远程连接git仓库 ssh -T gitgitee.com ssh -T gitcodeup.aliyun.com

黑马点评项目

遇到问题: 登录流程 session->JWT->SpringSession->tokenRedis (不需要改进为SpringSession,token更广泛,移动端或者前后端分离都可以用) SpringSession配置为redis模式后,redis相当于分布式se…

【AVRCP】AVRCP核心术语解析

目录 一、协议核心术语:架构的基石 1.1 音视频控制协议簇(AVRCP 生态链) 1.2 数据传输协议(L2CAP 核心术语) 二、设备架构术语:角色与交互 2.1 设备角色模型(CT/TG 二元架构) …

【弹性计算】异构计算云服务和 AI 加速器(四):FPGA 虚拟化技术

异构计算云服务和 AI 加速器(四):FPGA 虚拟化技术 🚀 FPGA(Field-Programmable Gate Array,现场可编程门阵列)是一种可重构的半导体芯片,允许用户根据需要动态配置硬件逻辑&#xff…

编译原理——自底向上语法优先分析

文章目录 自底向上优先分析概述一、自底向上优先分析概述二、简单优先分析法(一)优先关系定义(二)简单优先文法的定义(三)简单优先分析法的操作步骤 三、算法优先分析法(一)直观算符…

nuxt3网站文章分享微信 ,QQ功能

1.安装 npm install qrcode --save-dev 2.组件使用 <div class"share"><div style"line-height: 69px; color: #fff;width: 100px;"><p style"text-align: center;">分享:</p></div><div click"shareToMi…

STM32F103_LL库+寄存器学习笔记07 - 串口接收缓冲区非空中断

导言 上一章节《STM32F103_LL库寄存器学习笔记06 - 梳理串口与串行发送“Hello,World"》梳理完USART的基本设置与发送字符串“Hello,World"&#xff0c;接着梳理接收缓冲区非空中断。 实用的串口接收程序都会使用中断方式&#xff0c;不会使用轮询方式。最主要的原因…

生物中心论

Robert Lanza的“生物中心论”&#xff08;Biocentrism&#xff09;是一种以生命和意识为核心的宇宙观&#xff0c;试图颠覆传统科学对时间、空间和物质的理解。 一、核心观点 意识创造宇宙 生物中心论认为&#xff0c;宇宙的存在依赖于观察者的意识。传统科学将宇宙视为独立实…

Spring AOP:面向切面编程的探索之旅

目录 1. AOP 2. Spring AOP 快速入门 2.1 引入 Spring AOP 依赖 2.2 Spring AOP 简单使用 3. Spring AOP 核心概念 3.1 切点 3.1.1 Pointcut 定义切点 3.1.2 切点表达式 3.1.2.1 execution 表达式 3.1.2.2 annotation 表达式 3.2 连接点 3.3 通知(Advice) 3.3.1 通…

使用QT画带有透明效果的图

分辨率&#xff1a;24X24 最大圆 代码: #include <QApplication> #include <QImage> #include <QPainter>int main(int argc, char *argv[]) {QImage image(QSize(24,24),QImage::Format_ARGB32);image.fill(QColor(0,0,0,0));QPainter paint(&image);…

RocketMQ可视化工具使用 - Dashboard(保姆级教程)

1、github拉取代码&#xff0c;地址&#xff1a; https://github.com/apache/rocketmq-dashboard 2、指定Program arguments&#xff0c;本地启动工程 勾上这个Program arguments&#xff0c;会出现多一个对应的框 写入参数 --server.port1280 --rocketmq.config.namesrvAddr…

用Unity实现UDP客户端同步通信

制作UDPNetMgr网络管理模块 这段代码定义了一个名为UDPNetMgr的 Unity 脚本类&#xff0c;用于管理 UDP 网络通信&#xff0c;它作为单例存在&#xff0c;在Awake方法中创建收发消息的线程&#xff0c;Update方法处理接收到的消息&#xff1b;StartClient方法启动客户端连接&a…

pandoc安装及基础使用

pandoc安装 访问pandoc tags,切换至想要安装的版本&#xff0c;本次安装3.6.4 下载windows版本 下载texlive镜像&#xff0c;将文件转换成pdf需要用到 点开后会进入最近的镜像网站 下载完成后解压iso文件&#xff0c;以管理员身份运行install-tl-windows.bat&#xff…

3.27学习总结 算法题

自己用c语言做的&#xff0c;不尽如意 后面看了题解&#xff0c;用的是c&#xff0c;其中string 变量和字符串拼接感觉比c方便好多&#xff0c;可以用更少的代码实现更好的效果&#xff0c;打算之后去学习c&#xff0c;用c写算法。 递归&#xff0c;不断输入字符&#xff0c;…

案例分享|树莓派媒体播放器,重构商场广告的“黄金三秒”

研究显示&#xff0c;与传统户外广告相比&#xff0c;数字户外广告在消费者心中的记忆率提高了17%&#xff0c;而动态户外广告更是能提升16%的销售业绩&#xff0c;整体广告效率提升了17%。这一显著优势&#xff0c;使得越来越多资源和技术流入数字广告行业。 户外裸眼3D广告 无…

Redisson - 分布式锁和同步器

文章目录 锁&#xff08;Lock&#xff09;公平锁&#xff08;Fair Lock&#xff09;联锁&#xff08;MultiLock&#xff09;红锁&#xff08;RedLock&#xff09; 【已废弃】读写锁&#xff08;ReadWriteLock&#xff09;信号量&#xff08;Semaphore&#xff09;可过期许可信号…

Zustand 状态管理:从入门到实践

Zustand 状态管理&#xff1a;从入门到实践 Zustand 是一个轻量、快速且灵活的 React 状态管理库。它基于 Hooks API&#xff0c;提供了简洁的接口来创建和使用状态&#xff0c;同时易于扩展和优化。本文将通过一个 TODO 应用实例带你快速入门 Zustand&#xff0c;并探讨其核心…

PGP实现简单加密教程

模拟情景&#xff1a; 假设001和002两位同学的电脑上都安装了PGP&#xff0c;现在两人需要进行加密通讯。 一、创建密钥 1.新建密钥&#xff0c;输入名称和邮箱&#xff0c;输入8位口令&#xff0c;根据指示完成。 2.将其添加到主密钥&#xff0c;鼠标右击出现选项。 这里出…

7.8 窗体间传递数据

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的 当项目中有多个窗体时&#xff08;在本节中为两个窗体&#xff1a;Form1和Form2&#xff09;&#xff0c;窗体间传递数据有以下几种方…

【redis】集群 数据分片算法:哈希求余、一致性哈希、哈希槽分区算法

文章目录 什么是集群数据分片算法哈希求余分片搬运 一致性哈希扩容 哈希槽分区算法扩容相关问题 什么是集群 广义的集群&#xff0c;只要你是多个机器&#xff0c;构成了分布式系统&#xff0c;都可以称为是一个“集群” 前面的“主从结构”和“哨兵模式”可以称为是“广义的…