设计模式九:构建器模式 (Builder Pattern)

 动机(Motivation)

 1、在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
2、如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?

 基本概念

定义:构建器模式是一种创建型设计模式,它允许您分步骤创建复杂对象,使得相同的构建过程可以创建不同的表示。

构建器模式的核心思想是将复杂对象的构建与其表示分离,使得:

  • 客户端不需要知道对象内部的具体组成细节

  • 相同的构建过程可以创建不同的表示

  • 可以更精细地控制对象的构建过程

实现方式

1. 经典构建器模式实现

#include <iostream>
#include <memory>
#include <string>// 最终要构建的产品
class Pizza {
public:void setDough(const std::string& dough) {dough_ = dough;}void setSauce(const std::string& sauce) {sauce_ = sauce;}void setTopping(const std::string& topping) {topping_ = topping;}void showPizza() const {std::cout << "Pizza with " << dough_ << " dough, "<< sauce_ << " sauce and "<< topping_ << " topping." << std::endl;}private:std::string dough_;std::string sauce_;std::string topping_;
};// 抽象构建器
class PizzaBuilder {
public:virtual ~PizzaBuilder() = default;Pizza* getPizza() {return pizza_.get();}void createNewPizza() {pizza_ = std::make_unique<Pizza>();}virtual void buildDough() = 0;virtual void buildSauce() = 0;virtual void buildTopping() = 0;protected:std::unique_ptr<Pizza> pizza_;
};// 具体构建器 -  HawaiianPizzaBuilder
class HawaiianPizzaBuilder : public PizzaBuilder {
public:void buildDough() override {pizza_->setDough("cross");}void buildSauce() override {pizza_->setSauce("mild");}void buildTopping() override {pizza_->setTopping("ham+pineapple");}
};// 具体构建器 - SpicyPizzaBuilder
class SpicyPizzaBuilder : public PizzaBuilder {
public:void buildDough() override {pizza_->setDough("pan baked");}void buildSauce() override {pizza_->setSauce("hot");}void buildTopping() override {pizza_->setTopping("pepperoni+salami");}
};// 指导者 (Director) - 控制构建过程
class Cook {
public:void setPizzaBuilder(PizzaBuilder* pb) {pizzaBuilder_ = pb;}Pizza* getPizza() {return pizzaBuilder_->getPizza();}void constructPizza() {pizzaBuilder_->createNewPizza();pizzaBuilder_->buildDough();pizzaBuilder_->buildSauce();pizzaBuilder_->buildTopping();}private:PizzaBuilder* pizzaBuilder_;
};int main() {Cook cook;// 构建 Hawaiian PizzaHawaiianPizzaBuilder hawaiianBuilder;cook.setPizzaBuilder(&hawaiianBuilder);cook.constructPizza();Pizza* hawaiianPizza = cook.getPizza();hawaiianPizza->showPizza();  // 输出: Pizza with cross dough, mild sauce and ham+pineapple topping.// 构建 Spicy PizzaSpicyPizzaBuilder spicyBuilder;cook.setPizzaBuilder(&spicyBuilder);cook.constructPizza();Pizza* spicyPizza = cook.getPizza();spicyPizza->showPizza();  // 输出: Pizza with pan baked dough, hot sauce and pepperoni+salami topping.return 0;
}

2. 流式接口构建器 (更现代的C++实现)

#include <iostream>
#include <memory>
#include <string>class Computer {
public:void setCPU(const std::string& cpu) { cpu_ = cpu; }void setRAM(const std::string& ram) { ram_ = ram; }void setStorage(const std::string& storage) { storage_ = storage; }void setGPU(const std::string& gpu) { gpu_ = gpu; }void showSpecs() const {std::cout << "Computer Specs:\n"<< "CPU: " << cpu_ << "\n"<< "RAM: " << ram_ << "\n"<< "Storage: " << storage_ << "\n"<< "GPU: " << (gpu_.empty() ? "Integrated" : gpu_) << "\n";}private:std::string cpu_;std::string ram_;std::string storage_;std::string gpu_;
};class ComputerBuilder {
public:ComputerBuilder() : computer_(std::make_unique<Computer>()) {}ComputerBuilder& setCPU(const std::string& cpu) {computer_->setCPU(cpu);return *this;}ComputerBuilder& setRAM(const std::string& ram) {computer_->setRAM(ram);return *this;}ComputerBuilder& setStorage(const std::string& storage) {computer_->setStorage(storage);return *this;}ComputerBuilder& setGPU(const std::string& gpu) {computer_->setGPU(gpu);return *this;}std::unique_ptr<Computer> build() {return std::move(computer_);}private:std::unique_ptr<Computer> computer_;
};int main() {// 使用流式接口构建计算机auto gamingPC = ComputerBuilder().setCPU("Intel i9-13900K").setRAM("32GB DDR5").setStorage("2TB NVMe SSD").setGPU("NVIDIA RTX 4090").build();gamingPC->showSpecs();auto officePC = ComputerBuilder().setCPU("AMD Ryzen 5").setRAM("16GB DDR4").setStorage("512GB SSD").build();  // 没有设置GPUofficePC->showSpecs();return 0;
}

 UML结构

 

构建器模式的优点

  1. 分步构建:可以分步骤构建复杂对象

  2. 复用构建过程:相同的构建过程可以创建不同的产品

  3. 单一职责原则:将复杂对象的构建代码与其业务逻辑分离

  4. 更好的控制:对构建过程有更精细的控制

  5. 可扩展性:添加新的具体构建器无需修改现有代码

适用场景

  1. 当创建复杂对象的算法应该独立于该对象的组成部分及其装配方式时

  2. 当构造过程必须允许被构造的对象有不同的表示时

  3. 当需要避免"伸缩构造函数"问题(构造函数参数过多)时

  4. 当对象有大量可选组件或配置时

构建器模式的变体

  1. 流式接口构建器:通过方法链提供更优雅的API

  2. Groovy风格构建器:利用C++运算符重载实现更自然的语法

  3. 组合构建器:多个构建器协同工作构建复杂对象

注意事项

  1. 构建器模式会增加代码复杂度,因为需要创建多个新类

  2. 对于简单对象,直接使用构造函数可能更合适

  3. 确保构建器在构建完成后不能被重复使用(除非显式重置)

构建器模式在C++中特别适合用于创建配置复杂的对象,特别是当对象有许多可选组件时。流式接口的实现方式使得代码更加清晰易读。

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

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

相关文章

如何高效合并音视频文件

在自我学习或者进行视频剪辑的时候&#xff0c;经常从资源网址下载音视频分离的文件&#xff0c;例如audio_file1.m4a和video_1.mp4&#xff0c;之后需要把这两个文件合并在一起。于是条件反射得想要利用剪映等第三方工具&#xff0c;进行音视频的封装。可惜不幸的是&#xff0…

虚幻 5 与 3D 软件的协作:实时渲染,所见所得

《曼达洛人》的星际飞船在片场实时掠过虚拟荒漠&#xff0c;游戏开发者拖动滑块就能即时看到角色皮肤的通透变化&#xff0c;实时渲染技术正以 “所见即所得” 的核心优势&#xff0c;重塑着 3D 创作的整个逻辑。虚幻引擎 5&#xff08;UE5&#xff09;凭借 Lumen 全局光照和 N…

​Eyeriss 架构中的访存行为解析(腾讯元宝)

​Eyeriss 架构中的访存行为解析​Eyeriss 是 MIT 提出的面向卷积神经网络&#xff08;CNN&#xff09;的能效型 NPU&#xff08;神经网络处理器&#xff09;架构&#xff0c;其核心创新在于通过硬件结构优化访存行为&#xff0c;以解决传统 GPU 在处理 CNN 时因数据搬运导致的…

数字图像处理(三:图像如果当作矩阵,那加减乘除处理了矩阵,那图像咋变):从LED冬奥会、奥运会及春晚等等大屏,到手机小屏,快来挖一挖里面都有什么

数字图像处理&#xff08;三&#xff09;一、&#xff08;准备工作&#xff1a;咋玩&#xff0c;用什么玩具&#xff09;图像以矩阵形式存储&#xff0c;那矩阵一变、图像立刻跟着变&#xff1f;1. Python Jupyter Notebook/Lab 库 (NumPy, OpenCV, Matplotlib, scikit-image…

docker-desktop启动失败

报错提示deploying WSL2 distributions ensuring main distro is deployed: checking if main distro is up to date: checking main distro bootstrap version: getting main distro bootstrap version: open \\wsl$\docker-desktop\etc\wsl_bootstrap_version: The network n…

基于FastMCP创建MCP服务器的小白级教程

以下是基于windows 11操作系统环境的开发步骤。 1、python环境搭建 访问官网&#xff1a;https://www.python.org/。下载相应的版本&#xff08;如&#xff1a;3.13.5&#xff09;&#xff0c;然后安装。 安装完成之后&#xff0c;使用命令行工具输入python&#xff0c;显示…

网络协议与层次对应表

网络协议与层次对应表&#xff08;OSI & TCP/IP模型&#xff09;OSI七层模型TCP/IP四层模型协议/技术核心功能与应用​应用层​应用层HTTP/HTTPS网页传输协议&#xff08;HTTP&#xff09;及其加密版&#xff08;HTTPS&#xff09;FTP文件上传/下载协议SMTP/POP3/IMAPSMTP发…

android studio(NewsApiDemo)100%kotlin

api接口地址&#xff1a;https://newsapi.org/docs/get-started 项目成品地址&#xff1a;https://github.com/RushHan824/NewsApiDemo 项目效果展示&#xff1a; MVVM数据流 UML图 本系列文章将带你从零实现一个新闻列表App&#xff0c;适合零基础读者。一步步来&#xff0c…

面试高频题 力扣 417. 太平洋大西洋水流问题 洪水灌溉(FloodFill) 深度优先遍历(dfs) 暴力搜索 C++解题思路 每日一题

目录零、题目描述&#xff1a;用人话再讲一遍一、为什么这道题值得咱们学习&#xff1f;二、思路探索常规思路&#xff1a;逐个检查每个格子&#xff08;会超时&#xff01;⚠️&#xff09;三、正难则反&#xff1a;反向思维的巧妙应用 &#x1f504;&#xff08;思考时间&…

博物馆智慧导览系统AR交互与自动感应技术:从虚实融合到智能讲解的技术实践

本文面向博物馆信息化开发者、智慧场馆系统技术建设师及AR 设计工程师,从AR 交互与自动感应技术的逻辑出发,拆解AR虚实融合技术与智能讲解自动感应技术的原理&#xff0c;为相关开发者实践提供可复用的技术路径。如需获取博物馆智慧导览系统解决方案请前往文章最下方获取&#…

高效编程革命:DeepSeek V3多语言支持与性能优化实战

文章目录 如何利用DeepSeek V3编写高效程序代码:从原理到实践 引言 一、DeepSeek V3核心能力解析 1.1 模型架构与优势 1.2 与传统编程辅助工具对比 二、高效代码编写实践指南 2.1 精准提示工程(Prompt Engineering) 基础提示模板 高级提示技巧 2.2 生产级代码生成案例 示例:…

OkHttp 与 JSON 解析库完美结合:Moshi/Jackson/Gson 实战指南

前言在现代 Android 开发中&#xff0c;网络请求与 JSON 数据处理是密不可分的。OkHttp 作为强大的 HTTP 客户端&#xff0c;与 JSON 解析库&#xff08;Moshi/Jackson/Gson&#xff09;的结合使用&#xff0c;可以极大简化网络请求与数据解析的流程。本文将详细介绍如何将 OkH…

An error occurred at line: 1 in the generated java file问题处理及tomcat指定对应的jdk运行

一、背景 tomcat7启动后&#xff0c;加载jsp页面报错&#xff0c;提示无法将jsp编译为class文件&#xff0c;主要报错信息如下&#xff1a; An error occurred at line: 1 in the generated java file 最后确认该错误原因为&#xff1a;tomcat7不支持jdk1.8版本 机器上已配…

深入剖析大模型在文本生成式 AI 产品架构中的核心地位

一、大模型的崛起与概念解析 在人工智能技术飞速迭代的当下&#xff0c;大模型已成为驱动行业发展的核心引擎。从技术定义来看&#xff0c;大模型&#xff08;Large Model&#xff09; 是指基于深度学习架构、具备海量参数规模&#xff08;通常数十亿至数万亿级别&#xff09;&…

Vue Scoped样式:当动态元素成为“无家可归“的孤儿

引言&#xff1a;一场CSS的"身份危机"想象一下&#xff1a;你精心设计了一个Vue组件&#xff0c;为每个元素添加了漂亮的样式。你满意地添加了scoped属性&#xff0c;确保样式不会"越狱"影响其他组件。然后你动态添加了一些新元素&#xff0c;却发现它们完…

vmware分配了ubuntu空间但是ubuntu没有获取

一开始我看vmware中的ubuntu磁盘空间只有200g不够用&#xff0c;我在vmware给Ubuntu分了300G的磁盘空间&#xff0c;但是ubuntu还是只有之前的200g 如图在ubuntu查看后来发现&#xff0c;在磁盘软件里面需要自己分配磁盘空间大小拓展后就可以了

[MarkdownGithub] 使用块引用高亮显示“注意“和“警告“和其他注意方式的选项

参考来源: https://github.com/orgs/community/discussions/16925 Alerts are an extension of Markdown used to emphasize critical information. On GitHub, they are displayed with distinctive colors and icons to indicate the importance of the content. 提示框是 Ma…

mac测试ollama llamaindex

LlamaIndexs 将大语言模型和外部数据连接在一起的工具。大模型prompt有一个长度限制&#xff0c;当外部知识的内容超过这个长度&#xff0c;无法同时将有效信息传递给大模型&#xff0c;因此就诞生了 LlamaIndex。 具体操作就是通过多轮对话的方式不断提纯外部数据&#xff0c…

数据结构:字符串:大小写转换(changing case of a string)

目录 第一性问题&#xff1a;什么是“大小写”&#xff1f; 逐步构造代码&#xff1a;全部转为大写 我们现在用 第一性原理 的方式&#xff0c;从字符串与字符的本质出发&#xff0c;一步步推导出如何在 C 语言中将字符串中的字母变成全部大写或全部小写。 第一性问题&…

闲庭信步使用图像验证平台加速FPGA的开发:第三十二课——车牌识别的FPGA实现(4)车牌字符的分割定位

&#xff08;本系列只需要modelsim即可完成数字图像的处理&#xff0c;每个工程都搭建了全自动化的仿真环境&#xff0c;只需要双击top_tb.bat文件就可以完成整个的仿真&#xff0c;大大降低了初学者的门槛&#xff01;&#xff01;&#xff01;&#xff01;如需要该系列的工程…