建造者模式(大话设计模式)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 密钥客户端认证凭证(内置数据库密码认证、增强认证…...
7个核心价值点:Python学习路径与实战案例深度解析
7个核心价值点:Python学习路径与实战案例深度解析 【免费下载链接】Python-100-Days Python - 100天从新手到大师 项目地址: https://gitcode.com/GitHub_Trending/py/Python-100-Days Python作为一门多用途编程语言,在数据分析、Web开发、人工智…...
PyFluent:基于gRPC架构的Ansys Fluent Python自动化接口设计与实现
PyFluent:基于gRPC架构的Ansys Fluent Python自动化接口设计与实现 【免费下载链接】pyfluent Pythonic interface to Ansys Fluent 项目地址: https://gitcode.com/gh_mirrors/pyf/pyfluent PyFluent作为Ansys Fluent的官方Python接口,通过gRPC远…...
窗口管理效率革命:Topit如何重塑Mac多任务工作流
窗口管理效率革命:Topit如何重塑Mac多任务工作流 【免费下载链接】Topit Pin any window to the top of your screen / 在Mac上将你的任何窗口强制置顶 项目地址: https://gitcode.com/gh_mirrors/to/Topit 在数字化工作环境中,多任务处理已成为常…...
OpenClaw低配部署:gemma-3-12b-it在4GB内存设备上的运行方案
OpenClaw低配部署:gemma-3-12b-it在4GB内存设备上的运行方案 1. 为什么要在低配设备上部署OpenClaw? 去年我入手了一台二手Mac mini(8GB内存版),本想用它作为家庭媒体中心,后来突发奇想:能不能…...
医疗数据增强技巧:提升MedGemma在小数据集上的表现
医疗数据增强技巧:提升MedGemma在小数据集上的表现 1. 引言 当你手头只有几百张医疗影像数据,却要训练一个强大的MedGemma模型时,会不会觉得这是个不可能完成的任务?别担心,这恰恰是很多医疗AI开发者面临的真实困境。…...
DAMO-YOLO多模态实践:视觉+文本联合分析系统
DAMO-YOLO多模态实践:视觉文本联合分析系统 你有没有遇到过这样的情况?一个智能摄像头能认出画面里是“一辆车”,但它不知道这是“一辆正在送货的快递车”。或者,一个内容审核系统能识别出图片里有“文字”,却无法判断…...
实测科哥版HeyGem稳定性:文件校验、中断恢复、显存保护全解析
实测科哥版HeyGem稳定性:文件校验、中断恢复、显存保护全解析 1. 引言:为什么稳定性对数字人视频生成如此重要 在数字人视频生成领域,我们常常关注生成效果和速度,却容易忽视一个更基础的问题——稳定性。想象一下,当…...
单稳态vs双稳态电路全对比:从延时控制到状态保持的5个典型应用场景
单稳态与双稳态电路工程实战:5大应用场景深度解析与芯片选型指南 在物联网设备与自动化控制系统中,电路设计往往需要在瞬时响应与状态保持之间寻找平衡点。单稳态与双稳态电路作为两种基础却强大的电路结构,各自在特定场景下展现出独特优势。…...
红烧肉制作技术详解
红烧肉制作技术详解 红烧肉是一道传统的中式美食,以其色泽红亮、口感酥烂、味道浓郁而闻名。本文将详细介绍红烧肉的制作步骤及技巧,帮助你在家也能做出美味的红烧肉。 材料准备 五花肉 500克生姜 适量大葱 适量八角 2颗桂皮 1小块冰糖 适量料酒 适量老抽…...
SpringBoot + Ollama + Qdrant + DeepSeek:从零构建企业级本地知识库问答系统
1. 为什么选择这套技术栈? 在企业内部搭建知识库问答系统时,技术选型需要平衡性能、成本和易用性。这套组合拳的巧妙之处在于:SpringBoot提供企业级开发框架,Ollama让大模型本地化运行成为可能,Qdrant解决向量检索的效…...
