建造者模式(大话设计模式)C/C++版本
建造者模式
C++
参考:https://www.cnblogs.com/Galesaur-wcy/p/15907863.html
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;// Product Class,产品类,由多个部件组成。
class Product
{
private:vector<string> parts;public:// 添加产品部件void Add(string part){parts.push_back(part);}// 显示所有的产品部件void Show(){std::cout << "产品 创建" << std::endl;for_each(parts.cbegin(), parts.cend(), [](const string &s){ cout << s << " "; });cout << endl;}
};// Builder,抽象建造者,并声明一个得到产品建造后结果的方法GetResult。
class Builder
{
public:virtual ~Builder() = default;virtual void BuildPartA() = 0;virtual void BuildPartB() = 0;virtual Product *GetResult() = 0;
};// ConcreteBuilder1,具体建造者类,实现Builder接口中的具体方法。
class ConcreteBuilder1 : public Builder
{
private:Product *product = new Product;public:void BuildPartA() override{product->Add("部件A");}void BuildPartB() override{product->Add("部件B");}Product *GetResult() override{return product;}
};// ConcreteBuilder2,具体建造者类,实现Builder接口中的具体方法。
class ConcreteBuilder2 : public Builder
{
private:Product *product = new Product;public:void BuildPartA() override{product->Add("部件X");}void BuildPartB() override{product->Add("部件Y");}Product *GetResult() override{return product;}
};class Director // 指挥者类,指挥建造Product的过程(控制构建各部分组件的顺序)。
{
public:void Construct(Builder *const b){b->BuildPartA();b->BuildPartB();}
};int main()
{// 用户并不需要知道具体的建造过程,只需指定建造 Product 具体类型。Director director;Builder *b1 = new ConcreteBuilder1;Builder *b2 = new ConcreteBuilder2;cout << "用ConcreteBuilder1的方法建造产品: " << endl;director.Construct(b1);Product *p1 = b1->GetResult();p1->Show();cout << endl;cout << "用ConcreteBuilder2的方法建造产品: " << endl;director.Construct(b2);Product *p2 = b2->GetResult();p2->Show();cout << endl;delete p2;delete p1;delete b1;delete b2;p2 = p1 = nullptr;b1 = b2 = nullptr;return 0;
}
C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 产品部件
typedef struct Product
{char **parts;size_t parts_count;
} Product;// 构建者接口
typedef struct Builder
{void (*build_part_a)(Product *);void (*build_part_b)(Product *);Product *(*get_result)(void *);
} Builder;// 具体构建者基类,用于存储产品实例
typedef struct ConcreteBuilder
{Product product;
} ConcreteBuilder;// 导演类
typedef struct Director
{void (*construct)(struct Director *, Builder *, void *, Product **);
} Director;// 初始化产品
void init_product(Product *product)
{product->parts = NULL;product->parts_count = 0;
}// 释放产品
void free_product(Product *product)
{if (product->parts != NULL){int i;for (i = 0; i < product->parts_count; ++i){free(product->parts[i]);}free(product->parts);}
}// 添加部件到产品
void add_part(Product *product, const char *part)
{product->parts = (char **)realloc(product->parts, sizeof(char *) * (product->parts_count + 1));product->parts[product->parts_count++] = strdup(part);
}// 展示产品部件
void show_product(Product *product)
{printf("产品 创建:\n");int i;for (i = 0; i < product->parts_count; ++i){printf("%s ", product->parts[i]);}printf("\n");
}// 实现ConcreteBuilder1的构建方法
void build_part_a_concrete_builder1(Product *product)
{add_part(product, "部件A");
}void build_part_b_concrete_builder1(Product *product)
{add_part(product, "部件B");
}// 实现ConcreteBuilder2的构建方法
void build_part_a_concrete_builder2(Product *product)
{add_part(product, "部件X");
}void build_part_b_concrete_builder2(Product *product)
{add_part(product, "部件Y");
}// 获取结果的通用实现,确保安全返回产品实例
Product *get_result_common(void *builder_void_ptr)
{ConcreteBuilder *builder = (ConcreteBuilder *)builder_void_ptr;return &builder->product;
}// 导演类构建方法
void construct(Director *director, Builder *builder, void *builder_void_ptr, Product **result)
{builder->build_part_a((Product *)builder_void_ptr);builder->build_part_b((Product *)builder_void_ptr);*result = builder->get_result(builder_void_ptr);
}int main()
{// 初始化DirectorDirector director = {.construct = construct};// 初始化ConcreteBuilder实例ConcreteBuilder builder1;init_product(&builder1.product);Builder b1 = {.build_part_a = build_part_a_concrete_builder1,.build_part_b = build_part_b_concrete_builder1,.get_result = get_result_common};ConcreteBuilder builder2;init_product(&builder2.product);Builder b2 = {.build_part_a = build_part_a_concrete_builder2,.build_part_b = build_part_b_concrete_builder2,.get_result = get_result_common};Product *p1 = NULL;Product *p2 = NULL;printf("使用ConcreteBuilder1的方法建造产品: \n");director.construct(&director, &b1, &builder1, &p1);show_product(p1);puts("");printf("使用ConcreteBuilder2的方法建造产品: \n");director.construct(&director, &b2, &builder2, &p2);show_product(p2);puts("");free_product(p1);free_product(p2);return 0;
}
总结
- 创建者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时适用的模式;
- 使得建造代码与表示代码分离,隐藏了该产品是如何组装的,多疑若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了
相关文章:

建造者模式(大话设计模式)C/C++版本
建造者模式 C 参考:https://www.cnblogs.com/Galesaur-wcy/p/15907863.html #include <iostream> #include <vector> #include <algorithm> #include <string> using namespace std;// Product Class,产品类,由多个…...

【地质灾害监测实现有效预警,44人提前安全转移】
6月13日14时,国信华源地质灾害监测预警系统提前精准预警,安全转移10户44人。 该滑坡隐患点通过科学部署国信华源裂缝计、倾角加速度计、雨量计、预警广播等自动化、智能化监测预警设备,实现了对隐患点裂缝、位移、降雨量等关键要素的实时动态…...
Ruby 数据库访问 - DBI 教程
Ruby 数据库访问 - DBI 教程 本文将详细介绍如何使用 Ruby 的 DBI(Database Interface)库来访问和操作数据库。DBI 是 Ruby 语言中一个常用的数据库接口库,它提供了一套统一的接口来访问不同的数据库系统,如 MySQL、PostgreSQL、SQLite 等。通过本文的学习,您将掌握如何使…...

Linux环境搭建之CentOS7(包含静态IP配置)
🔥 本文由 程序喵正在路上 原创,CSDN首发! 💖 系列专栏:虚拟机 🌠 首发时间:2024年6月22日 🦋 欢迎关注🖱点赞👍收藏🌟留言🐾 安装VMw…...

Dell戴尔灵越Inspiron 16 Plus 7640/7630笔记本电脑原装Windows11下载,恢复出厂开箱状态预装OEM系统
灵越16P-7630系统包: 链接:https://pan.baidu.com/s/1Rve5_PF1VO8kAKnAQwP22g?pwdjyqq 提取码:jyqq 灵越16P-7640系统包: 链接:https://pan.baidu.com/s/1B8LeIEKM8IF1xbpMVjy3qg?pwdy9qj 提取码:y9qj 戴尔原装WIN11系…...
.NET C# 装箱与拆箱
.NET C# 装箱与拆箱 目录 .NET C# 装箱与拆箱1 装箱 (Boxing)1.1 过程:1.2 示例: 2 拆箱 (Unboxing)2.1 过程:2.2 示例: 3 性能影响4 性能优化4.1 使用泛型集合示例: 4.2 使用Nullable<T>示例: 4.3 避…...

springboot与flowable(9):候选人组
act_id_xxx相关表存储了所有用户和组的数据。 一、维护用户信息 Autowiredprivate IdentityService identityService;/*** 维护用户*/Testvoid createUser() {User user identityService.newUser("zhangsan");user.setEmail("zhangsanqq.com");user.setF…...

为什么要选择华为 HCIE-Security 课程?
2020 年我国网络安全市场规模达到 680 亿元,同比增长 25%。随着对网络安全的愈加重视及布局,市场规模将持续扩大。 近年来,随着“云大物工移智”等新兴技术的快速发展和普及应用,数字化已经融入社会经济生活的方方面面,…...
C++之std::queue::emplace
std::queue::emplace 是 C STL 中 std::queue 容器的成员函数,它用于在队列的末尾就地构造一个新元素。这个函数类似于 std::queue::push,但是 emplace 允许你通过传递参数来构造元素,而不需要显式地创建一个元素对象。 理解 std::queue::em…...

Vue3 - 在项目中使用vue-i18n不生效的问题
检查和配置 Vue I18n 确保你已经正确安装了Vue I18n并且配置了组合API模式。 安装 Vue I18n npm install vue-i18nnext配置 i18n.js import { createI18n } from vue-i18n; import messages from ./messages;const i18n createI18n({legacy: false, // 使用组合 API 模式l…...

Day 44 Ansible自动化运维
Ansible自动化运维 几种常用运维工具比较 Puppet —基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱ruby SaltStack —基于 Python 开发,采用 C/S 架构,相对 puppet 更轻量级,配置语法使用 YAML,使得配置脚本更简单 Ansible —基于 …...

Excel/WPS《超级处理器》功能介绍与安装下载
超级处理器是基于Excel或WPS开发的一款插件,拥有近300个功能,非常简单高效的处理表格数据,安装即可使用。 点击此处:超i处理器安装下载 Excel菜单,显示如下图所示: WPS菜单显示,如下图所示&am…...

U-Net for Image Segmentation
1.Unet for Image Segmentation 笔记来源:使用Pytorch搭建U-Net网络并基于DRIVE数据集训练(语义分割) 1.1 DoubleConv (Conv2dBatchNorm2dReLU) import torch import torch.nn as nn import torch.nn.functional as F# nn.Sequential 按照类定义的顺序去执行模型&…...
POI导入带有合并单元格的excel,demo实例,直接可以运行
直接可以运行 import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.s…...

【C语言】解决C语言报错:Use-After-Free
文章目录 简介什么是Use-After-FreeUse-After-Free的常见原因如何检测和调试Use-After-Free解决Use-After-Free的最佳实践详细实例解析示例1:释放内存后未将指针置为NULL示例2:多次释放同一指针示例3:全局或静态指针被释放后继续使用示例4&am…...
C语言经典例题-19
1.字符串左旋结果 题目内容:写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。 例:给定s1 AABCD和s2 BCDAA,返回1 给定s1 abcd和s2 ACBD,返回0 AABCD左旋一个字符得到ABCDA AABCD左旋两个字符得到BCDAA AABCD右旋一…...

AlmaLinux 更换CN镜像地址
官方镜像列表 官方列表:https://mirrors.almalinux.org/CN 开头的站点,不同区域查询即可 一键更改镜像地址脚本 以下是更改从默认更改到阿里云地址 cat <<EOF>>/AlmaLinux_Update_repo.sh #!/bin/bash # -*- coding: utf-8 -*- # Author:…...

【笔记】【矩阵的二分】668. 乘法表中第k小的数
力扣链接:题目 参考地址:参考 思路:二分查找 把矩阵想象成一维的已排好序的数组,用二分法找第k小的数字。 假设m行n列,则对应一维下标范围是从1到mn,初始: l1; rmn; mid(lr)/2 设mid在第i行&a…...

红米手机RedNot11无法使用谷歌框架,打开游戏闪退的问题,红米手机如何开启谷歌框架
红米手机RedNot11无法使用谷歌框架,打开游戏闪退的问题, 1.问题描述2.问题原因3.解决方案3.1配置谷歌框架:3.1软件优化 4.附图 1.问题描述 红米手机打开安卓APP没有广告,直接闪退,无法使用谷歌框架 异常关键词中包含&…...

emqx5.6.1 数据、配置备份与迁移
EMQX 支持导入和导出的数据包括: EMQX 配置重写的内容: 认证与授权配置规则、连接器与 Sink/Source监听器、网关配置其他 EMQX 配置内置数据库 (Mnesia) 的数据 Dashboard 用户和 REST API 密钥客户端认证凭证(内置数据库密码认证、增强认证…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)
+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...

DeepSeek越强,Kimi越慌?
被DeepSeek吊打的Kimi,还有多少人在用? 去年,月之暗面创始人杨植麟别提有多风光了。90后清华学霸,国产大模型六小虎之一,手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水,单月光是投流就花费2个亿。 疯…...

深入理解 C++ 左值右值、std::move 与函数重载中的参数传递
在 C 编程中,左值和右值的概念以及std::move的使用,常常让开发者感到困惑。特别是在函数重载场景下,如何合理利用这些特性来优化代码性能、确保语义正确,更是一个值得深入探讨的话题。 在开始之前,先提出几个问题&…...

第2课 SiC MOSFET与 Si IGBT 静态特性对比
2.1 输出特性对比 2.2 转移特性对比 2.1 输出特性对比 器件的输出特性描述了当温度和栅源电压(栅射电压)为某一具体数值时,漏极电流(集电极电流...