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

「软件设计模式」建造者模式(Builder)

深入解析建造者模式:用C++打造灵活对象构建流水线

引言:当对象构建遇上排列组合

在开发复杂业务系统时,你是否经常面对这样的类:它有20个成员变量,其中5个是必填项,15个是可选项。当用户需要创建豪华套餐A(含加冰可乐)基础套餐B(不要洋葱)时,传统的构造函数早已不堪重负。这正是建造者模式(Builder Pattern)大展拳脚的舞台!

一、模式精髓解析

建造者模式通过分步构建的方式解耦复杂对象的创建过程,让同一构建流程能产出不同表现形式的产品。就像麦当劳的点餐系统:选择汉堡基底→添加配料→选择饮料→完成套餐组合。

二、C++模式实现结构

核心组件拆解

  1. Product(产品):需要构建的复杂对象
  2. Builder(抽象建造者):定义构建步骤的接口
  3. ConcreteBuilder(具体建造者):实现具体构建逻辑
  4. Director(指挥者):控制构建流程(可选)

三、实战:定制汉堡套餐系统

我们以快餐店汉堡套餐系统为例,演示如何实现不同配置的套餐组合。

1. 产品类定义

#include <iostream>
#include <memory>
#include <string>
#include <vector>class HamburgerMeal {
public:void showMeal() const {std::cout << "=== 您的套餐配置 ===" << std::endl;std::cout << "主餐: " << mainItem << std::endl;std::cout << "饮料: " << drink << std::endl;std::cout << "附加项: ";for (const auto& item : sides) {std::cout << item << " ";}std::cout << "\n甜点: " << (dessert.empty() ? "无" : dessert) << std::endl;}private:friend class MealBuilder; // 允许建造者访问私有成员std::string mainItem;std::string drink;std::vector<std::string> sides;std::string dessert;
};

2. 建造者实现

class MealBuilder {
public:MealBuilder() = default;MealBuilder& setMain(const std::string& main) {meal.mainItem = main;return *this;}MealBuilder& setDrink(const std::string& drink) {meal.drink = drink;return *this;}MealBuilder& addSide(const std::string& side) {meal.sides.push_back(side);return *this;}MealBuilder& setDessert(const std::string& dessert) {meal.dessert = dessert;return *this;}HamburgerMeal build() {// 验证必要参数if (meal.mainItem.empty()) {throw std::invalid_argument("必须指定主餐");}return meal;}private:HamburgerMeal meal;
};

3. 客户端调用

#include "../../include/header.h"
#include "buger.h"
#include "meal_builder.h"
int main() {try {// 豪华套餐HamburgerMeal premiumMeal = MealBuilder().setMain("安格斯牛肉汉堡").setDrink("大杯可乐").addSide("薯条").addSide("鸡块").setDessert("苹果派").build();// 简约套餐HamburgerMeal simpleMeal = MealBuilder().setMain("经典鸡腿堡").setDrink("小杯雪碧").build();premiumMeal.showMeal();std::cout << "\n";simpleMeal.showMeal();} catch (const std::exception& e) {std::cerr << "套餐创建失败: " << e.what() << std::endl;}return 0;
}

4.执行结果

四、高级技巧:支持多种预设配置

class MealPreset {
public:static HamburgerMeal createChildrenMeal() {return MealBuilder().setMain("迷你汉堡").setDrink("牛奶").addSide("水果杯").setDessert("小饼干").build();}static HamburgerMeal createComboMeal() {return MealBuilder().setMain("双层牛肉堡").setDrink("中杯可乐").addSide("薯条").build();}
};

五、模式优势深度解析

🚀 C++实现特色优势

  1. 强类型检查:编译期发现类型错误
  2. RAII支持:自动资源管理
  3. 移动语义:高效的对象传递
  4. 灵活内存控制:支持栈对象和智能指针

💡 适用场景扩展

  1. 需要生成的对象有多个变体
  2. 对象创建需要多个步骤的初始化
  3. 需要隔离复杂对象的创建细节
  4. 需要支持不同地区配置(如语言包加载)

六、性能优化策略

  1. 参数预校验:在build()前进行参数检查
  2. 使用移动语义:减少对象拷贝开销
  3. 对象池技术:对频繁创建的对象进行缓存
  4. const正确性:确保构建后的对象不可变

七、与工厂模式对比

特性建造者模式工厂模式
构建重点分步骤构建复杂对象直接创建完整对象
参数处理支持可选参数和分步设置通常需要一次性传递所有参数
对象复杂度适合构建多部件组成的复杂对象适合创建单一结构的对象
扩展性通过新增Builder实现不同配置通过子类化工厂来创建不同对象
典型C++实现链式方法+友元类静态工厂方法/抽象工厂

八、现代C++增强实现

// 使用现代C++特性优化建造者
template<typename T>
class GenericBuilder {
protected:T object;public:operator T() && {  // 右值转换运算符return std::move(object);}T build() && {     // 右值build方法return std::move(object);}
};class ModernMeal : public GenericBuilder<ModernMeal> {
public:ModernMeal& setMain(std::string main) {object.mainItem = std::move(main);return *this;}// 其他设置方法类似...
};

九、最佳实践指南

  1. 防御性编程:在build()中进行参数合法性检查
  2. 清晰的接口设计:保持方法命名直观(withXxx(), addXxx())
  3. 不可变对象:构建完成后锁定对象状态
  4. 文档注释:明确每个构建步骤的作用域和约束条件
  5. 异常安全:确保在异常发生时资源正确释放

总结:构建的艺术

建造者模式如同一位经验丰富的建筑大师,将看似混乱的构建过程转化为标准化的装配流程。在C++的世界中,通过合理运用友元类、移动语义和模板技术,我们能够打造出既高效又灵活的对象构建系统。记住,好的设计模式应用应该像呼吸一样自然,而不是生硬的教条堆砌。

相关文章:

「软件设计模式」建造者模式(Builder)

深入解析建造者模式&#xff1a;用C打造灵活对象构建流水线 引言&#xff1a;当对象构建遇上排列组合 在开发复杂业务系统时&#xff0c;你是否经常面对这样的类&#xff1a;它有20个成员变量&#xff0c;其中5个是必填项&#xff0c;15个是可选项。当用户需要创建豪华套餐A&…...

Matlab 机器人 雅可比矩阵

工业机器人运动学与Matlab正逆解算法学习笔记&#xff08;用心总结一文全会&#xff09;&#xff08;四&#xff09;——雅可比矩阵_staubli机器人正逆向运动学实例验证matlab-CSDN博客 matlab求雅可比矩阵_六轴机械臂 矢量积法求解雅可比矩阵-CSDN博客 (63 封私信 / 80 条消息…...

DeepSeek 助力 Vue 开发:打造丝滑的面包屑导航(Breadcrumbs)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…...

IntelliJ IDEA 2024.1.4版无Tomcat配置

IntelliJ IDEA 2024.1.4 (Ultimate Edition) 安装完成后&#xff0c;调试项目发现找不到Tomcat服务&#xff1a; 按照常规操作添加&#xff0c;发现服务插件中没有Tomcat。。。 解决方法 1、找到IDE设置窗口 2、点击Plugins按钮&#xff0c;进入插件窗口&#xff0c;搜索T…...

chrome://version/

浏览器输入&#xff1a; chrome://version/ Google浏览器版本号以及安装路径 Google Chrome131.0.6778.205 (正式版本) &#xff08;64 位&#xff09; (cohort: Stable) 修订版本81b36b9535e3e3b610a52df3da48cd81362ec860-refs/branch-heads/6778_155{#8}操作系统Windows…...

知识图谱数据库 Neo4j in Docker笔记

下载 docker pull neo4j:community官方说明 https://neo4j.com/docs/operations-manual/2025.01/docker/introduction/ 启动 docker run \--restart always \--publish7474:7474 --publish7687:7687 \--env NEO4J_AUTHneo4j/your_password \--volumeD:\files\knowledgegrap…...

【动手学强化学习】02多臂老虎机

问题定义 强化学习关注的是在于环境交互中学习&#xff0c;是一种试错学习的范式。在正式进入强化学习之前&#xff0c;我们先来了解多臂老虎机问题。该问题也被看作简化版的强化学习&#xff0c;帮助我们更快地过度到强化学习阶段。 有一个拥有 K K K 根拉杆的老虎机&#…...

【网络编程】之Udp网络通信步骤

【网络编程】之Udp网络通信步骤 TCP网络通信TCP网络通信的步骤对于服务器端对于客户端 TCP实现echo功能代码实现服务器端getsockname函数介绍 客户端效果展示 对比两组函数 TCP网络通信 TCP网络通信的步骤 对于服务器端 创建监听套接字。&#xff08;调用socket函数&#xff…...

Java 基于 SpringBoot+Vue 的家政服务管理平台设计与实现

博主介绍&#xff1a;✌程序员徐师兄、8年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战*✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447…...

架构——Nginx功能、职责、原理、配置示例、应用场景

以下是关于 Nginx 的功能、职责、原理、配置示例、应用场景及其高性能原因的详细说明&#xff1a; 一、Nginx 的核心功能 1. 静态资源服务 功能&#xff1a;直接返回静态文件&#xff08;如 HTML、CSS、JS、图片、视频等&#xff09;。配置示例&#xff1a;server {listen 80…...

Spring Boot中使用Flyway进行数据库迁移

文章目录 概要Spring Boot 集成 FlywayFlyway 其他用法bug错误Flyway版本不兼容数据库存在表了Flyway 的校验和&#xff08;Checksum&#xff09;不匹配 概要 在 Spring Boot 项目开发中&#xff0c;数据库的变更不可避免。手动执行 SQL 脚本不仅容易出错&#xff0c;也难以维…...

CAS单点登录(第7版)9.属性

如有疑问&#xff0c;请看视频&#xff1a;CAS单点登录&#xff08;第7版&#xff09; 属性 属性定义 概述 属性定义 从身份验证或属性存储库源获取和解析 CAS 中属性的定义时&#xff0c;往往使用其名称进行定义和引用&#xff0c;而无需任何其他元数据或修饰。例如&#…...

137,【4】 buuctf web [SCTF2019]Flag Shop

进入靶场 都点击看看 发现点击work会增加&#xffe5; 但肯定不能一直点下去 抓包看看 这看起来是一个 JWT&#xff08;JSON Web Token&#xff09;字符串。JWT 通常由三部分组成&#xff0c;通过点&#xff08;.&#xff09;分隔&#xff0c;分别是头部&#xff08;Header&…...

P9853 [入门赛 #17] 方程求解

P9853 [入门赛 #17] 方程求解 - 洛谷 题目描述 小A有n个关于x的方程&#xff0c;第i个方程形如ai​xi​bi​ci​。方程的解x均为正整数&#xff0c;例如下面几个方程都是符合要求的方程&#xff1a; 2x 4 10 -3x 13 10 4x - 8 16 其中&#xff0c;第一组方程的解为x1​…...

【网络安全 | 漏洞挖掘】跨子域账户合并导致的账户劫持与删除

未经许可,不得转载。 文章目录 概述正文漏洞成因概述 在对目标系统进行安全测试时,发现其运行着两个独立的域名——一个用于司机用户,一个用于开发者/企业用户。表面上看,这两个域名各自独立管理账户,但测试表明它们在处理电子邮件变更时存在严重的逻辑漏洞。该漏洞允许攻…...

spring集成activiti流程引擎(源码)

前言 activiti工作流引擎项目&#xff0c;企业erp、oa、hr、crm等企事业办公系统轻松落地&#xff0c;请假审批demo从流程绘制到审批结束实例。 源码获取&#xff1a;本文末个人名片直接获取。 一、项目形式 springbootvueactiviti集成了activiti在线编辑器&#xff0c;流行…...

ROS基本功能

1.Topic话题与Message消息&#xff08;主要通讯方式&#xff09; 基本规则 发布消息的步骤 常用工具 话题的订阅 使用launch启动多个节点...

C++基础系列【13】类的成员初始化

博主介绍&#xff1a;程序喵大人 35- 资深C/C/Rust/Android/iOS客户端开发10年大厂工作经验嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手《C20高级编程》《C23高级编程》等多本书籍著译者更多原创精品文章&#xff0c;首发gzh&#xff0c;见文末&#x1f447;&#x1f…...

Redis 03章——10大数据类型概述

一、which10 &#xff08;1&#xff09;一图 &#xff08;2&#xff09;提前声明 这里说的数据类型是value的数据类型&#xff0c;key的类型都是字符串 官网&#xff1a;Understand Redis data types | Docs &#xff08;3&#xff09;分别是 1.3.1redis字符串&#xff0…...

Ubuntu 上安装 Elasticsearch 7.6.0

要在 Ubuntu 24.04 上安装 Elasticsearch 7.6.0&#xff0c;可以按照以下步骤进行&#xff1a; 步骤 1: 更新系统依赖 确保系统是最新的&#xff0c;并安装必要的依赖包&#xff1a; sudo apt update sudo apt upgrade -y sudo apt install -y apt-transport-https openjdk-1…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...