设计模式 创建者模式
设计模式 创建者模式
- 前言
- 原来代码
- 使用设计模式
- 总结
- Builder模式在源码中的应用:
- 其他代码
前言
-
“对象创建”模式——绕开new
工厂模式 抽象工厂 原型模式 构建器
-
动机与背景
目前需要建造一个房子,建造房子需要一系列特定的步骤,但是房子的类型也有很多,不同类型的房子对应的建造步骤也不尽相同。
用于分步骤构建对象 -
没有使用设计模式的代码
// 可以参照模板方法
-
存在的问题
个人感觉与模板方式很相似,所以上面的代码使用了模板方法的代码
-
解决方法
使用构建器,将复杂多变的对象的构建过程抽象出来
-
使用设计模式的代码
原来代码
Builder 模式主要用于“分步骤构建一个复杂的对象”。
在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。
变化点在哪里,封装哪里—— Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动。
其缺点在于难以应对“分步骤构建算法”的需求变动。在Builder模式中,要注意不同语言中构造器内调用虚函数的差别(C++ vs. C#) 。
//原来的代码
class House{protected:void init(){ //1.构建的流程是稳定的this -> BuildPart1(); // 打地基for(int i = 0 ; i < 4 ; i ++){this -> BuildPart2();}bool flag = this -> BuildPart3();if(flag){this -> BuildPart4(); }this -> BuildPart5(); }virtual ~House(){}//代表建房子的门 窗户 等 ,2.构建的方法是变化的,纯虚函数virtual void BuildPart1() = 0;virtual void BuildPart2() = 0;virtual void BuildPart3() = 0;virtual void BuildPart4() = 0;virtual void BuildPart5() = 0;};
在这里有个问题是,能不能把init函数名替换成构造函数:不能,C++构造函数是静态绑定
class StoneHose:public House{protected: //实例化virtual void BuildPart1(){...............}virtual void BuildPart2(){...............}virtual void BuildPart3(){...............}virtual void BuildPart4(){...............}virtual void BuildPart5(){...............}
};
到这里已经完成了,使用:
int main()
{//就是父类指针指向子类对象House * pHouse = new StoneHose();pHouse ->Init();}
使用设计模式
//把上面的代码,用设计模式
//如果对象比较复杂,可以做如下拆分,把House分成两个,一个是定义方法(可变)的叫做HouseBuilder ,一个定义流程、逻辑的是把init放进去
class House{//........void Part1();void Part2();void Part3();};class HouseBuilder{public:House *GetResult() {return pHouse;} virtual ~HouseBuilder(){}protected://代表建房子的门 窗户 等 ,2.构建的方法是变化的,纯虚函数virtual void BuildPart1() = 0;virtual void BuildPart2() = 0;virtual void BuildPart3() = 0;virtual void BuildPart4() = 0;virtual void BuildPart5() = 0;};
//塞一个 HouseBulider指针,把 this 换成pHouseBuilder
class HouseDirector{public:HouseBulider *pHouseBuilder;//另外要加入构造函数HouseDirector(HouseBulider *pH){ //新加入this -> pHouseBuilder = pH;}HouseBulider Construct(){//void init() 构建过程,不是虚函数pHouseBuilder -> BuildPart1(); // 打地基for(int i = 0 ; i < 4 ; i ++){pHouseBuilder -> BuildPart2();//把init()中的 this 换成pHouseBuilder}bool flag = pHouseBuilder -> BuildPart3();if(flag){pHouseBuilder -> BuildPart4(); }pHouseBuilder -> BuildPart5(); return pHouseBuilder->GetResult();}
}
//那么石头房子呢 StoneHose:public House 感觉这里是不需要呀 看这个https://zhuanlan.zhihu.com/p/665141864
class StoneHose:public House{ //对象的表示};class StoneHoseBuilder:public HouseBuilder{ // 实现protected: virtual void BuildPart1(){...............}virtual void BuildPart2(){...............}virtual void BuildPart3(){...............}virtual void BuildPart4(){...............}virtual void BuildPart5(){...............}
};
void main() {StoneHouseBuilder *pStoneHouseBuilder = new StoneHouseBuilder;HouseDirector *pHouseDirector = new HouseDirector(HouseBuilder *pStoneHouseBuilder);pHouseDirector->Construct();// 操作
}
构建过程太复杂,抽象出来单独变成类
把对象的表示和构建相分离,(House 和 HouseBuilder),是的同样的构建(稳定)过程(Construct)可以构建不同的表示(变化)
上面只是一个演化模式,
总结
总结一下,就是把一个有构建步骤的对象拆分,分成表示和实现方法过程,实现过程稳定(不抽象),表示部分可以抽象,用虚函数实现
class A{//需要创建的事物、对象,这里定义A的组成
set_Part1();
}
class B_builer (方法接口){ //A的组成实现接口,要有能返回A的接口
//1.要拥有A指针成员 A *m_a
//2.要拥有构造函数,传入A,实现多态 B_builer(A a){this->m_a = a;}
//3.要有返回A 的方法接口 A GetComputer()
//4.要定义建造A需要的方法接口:buildPart1 2 3 4 …
A *m_a ;
B_builer(A *a){this->m_a = a;}
virtual buildPart1() = 0;
virtual A* GetComputer() = 0; // 要有返回A 的方法接口
};
class B_concrete_builer (方法实现):public B_builer{
virtual buildPart1(){ this -> A->setPart1();} //具体实现
virtual A* GetComputer(){return tbis->A ;}; // 具体实现 要有返回A 的方法接口
};
class C_Process (稳定的构建过程)
{
//1.要拥有建造(材料)的方法接口的指针成员 B_builer *m_b_builer
B_builer *m_b_builer ;
//2.要拥有构造函数,传入B_builer,实现多态
C_Process(B_builer *b_builer){this->m_b_builer = b_builer;}
//2,稳定的构建过程代码(建造逻辑) ,要返回A
A *func(){
step 1 2 3 …
return m_b_builer->GetResult();
}
}
使用过程:
B_concrete_builer *B = new B_concrete_builer();
C_Process *C = new C_Process(B);
C->func();
A = B->GetComputer();
Builder模式在源码中的应用:
StringBuilder
其实我们熟知的StringBuilder就是builder模式的典型实现。我们平时使用基本都是这样:
1 StringBuilder sb = new StringBuilder();
2 sb.append(123).append(‘a’)
3 .append(1.23)
4 .append(true)
5 .append(“hhhh”);
https://zhuanlan.zhihu.com/p/113971558
其他代码
这个很好:
https://zhuanlan.zhihu.com/p/665141864
//下面是源码
#include <iostream>
using namespace std;#include <string>//需要的产品:笔记本电脑
class Computer {
public:void SetCPU(const string cpu) {this->cpu = cpu;}void SetDisk(const string disk) {this->disk = disk;}void SetMemory(const string memory) {this->memory = memory;}void SetScreen(const string screen) {this->screen = screen;}void ShowInfo() {cout << "======基本信息======" << endl;cout << this->cpu << endl;cout << this->memory << endl;cout << this->disk << endl;cout << this->screen << endl;cout << "====================" << endl;}private:string cpu; //CPUstring disk; //磁盘string memory; //内存string screen; //显示屏
};//抽象的建造者:抽象建造单位
class Builder
{
public:virtual void BuilderCpu() = 0; //建造CPUvirtual void BuilderMemory() = 0; //建造内存virtual void BuilderDisk() = 0; //建造磁盘virtual void BuilderScreen() = 0; //建造显示屏virtual Computer* GetComputer() = 0; //出厂建造好的笔记本
};//具体的建造者:具体施工单位、具体的建造方式
class DellBuilder : public Builder //dell笔记本
{
private:Computer* computer;
public:DellBuilder() {this->computer = new Computer(); }void BuilderCpu() {this->computer->SetCPU("DELL CPU");}void BuilderMemory() {this->computer->SetMemory("DELL 内存");}void BuilderDisk() {this->computer->SetDisk("Dell 磁盘");}void BuilderScreen() {this->computer->SetScreen("DELL 显示屏");}Computer* GetComputer(){return this->computer;}};//具体的建造者:具体施工单位、具体的建造方式
class AppleBuilder : public Builder //dell笔记本
{private:Computer* computer;
public:AppleBuilder() {this->computer = new Computer(); }void BuilderCpu() {this->computer->SetCPU("Apple CPU");}void BuilderMemory() {this->computer->SetMemory("Apple 内存");}void BuilderDisk() {this->computer->SetDisk("Apple 磁盘");}void BuilderScreen() {this->computer->SetScreen("Apple 显示屏");}Computer* GetComputer(){return this->computer;}};//指导者:指挥具体的建造逻辑
class Director
{
public:Director(Builder* builder) {this->builder = builder;}//建造逻辑void BuilderComputer() {//1.建造CPUthis->builder->BuilderCpu();cout << "first make cpu" << endl;//2.建造内存条this->builder->BuilderMemory();cout << "second make memory" << endl;//3.建造磁盘this->builder->BuilderDisk();cout << "third make disk" << endl;//4.建造显示屏this->builder->BuilderScreen();cout << "finally, make screen" << endl;}private:Builder* builder;
};//客户端
int main()
{Computer* computer = NULL;Builder* builder = NULL;Director* director = NULL;//需求:要一台dell笔记本builder = new DellBuilder(); // 先找一个dell制造厂,负责具体的创建director = new Director(builder); //指导者,指导Dell制造厂如何创建director->BuilderComputer(); //开始创建了。。。computer = builder->GetComputer(); // 待建造完毕,制造厂出货computer->ShowInfo(); //产品质检合格delete computer;delete director;delete builder;//制造Aplle比较笔记本,同理可得。return 0;
}
相关文章:
设计模式 创建者模式
设计模式 创建者模式 前言原来代码使用设计模式总结Builder模式在源码中的应用:其他代码 前言 “对象创建”模式——绕开new 工厂模式 抽象工厂 原型模式 构建器 动机与背景 目前需要建造一个房子,建造房子需要一系列特定的步骤,但是房子的类…...

排序算法--插入排序
实现逻辑 ① 从第一个元素开始,该元素可以认为已经被排序 ② 取出下一个元素,在已经排序的元素序列中从后向前扫描 ③如果该元素(已排序)大于新元素,将该元素移到下一位置 ④ 重复步骤③,直到找到已排序的元…...

【操作宝典】SQL巨擘:掌握SQL Server Management的终极秘籍!
目录 ⛳️【SQL Server Management】 ⛳️1. 启动登录 ⛳️2. 忘记密码 ⛳️3. 操作数据库和表 3.1 新建数据库text 3.2 新建表 3.3 编辑表 3.4 编写脚本 ⛳️【SQL Server Management】 ⛳️1. 启动登录 需要开启服务 ⛳️2. 忘记密码 登录windows--> 安全性 -->…...

Airtest遇到模拟器无法输入中文的情况该如何处理?
1. 前言 最近有收到同学们的一些提问,使用Airtest的 text 接口,发现在部分模拟器上, text 无法输入中文,不知道该怎么处理。 今天我们就输入这个小问题,来详细聊一下。 2. Airtest的输入法简介 对于Android设备来说…...
从农夫山泉家族任命,看“食企二代”的接班与传承
本文转载自产业科技 农夫山泉再次引发舆论关注,起因是一则人事任命消息。 市场消息称,农夫山泉对区域及人员进行了调整,其总部所在地浙江省被划分为四个区域,在以往浙南、浙北基础上多了浙西大区以及杭州大区,其中农…...
JavaScript启动本地应用程序
JavaScript调起本地应用程序 以下内容,自定义部分我也还未经过实际验证,酌情查看。 文章目录 JavaScript调起本地应用程序确定协议调用协议传参自定义写入协议获取参数 在浏览器中通过 JavaScript调起本地应用程序的一个可行方法就是 通过协议调起。 …...
软件工程理论与实践 (吕云翔)第十四章 软件维护与软件工程管理课后习题与解析
第十四章 软件维护与软件工程管理 1.判断题 (1)代码行技术是比较简单的定量估算软件规模的方法。(√) (2)功能点技术依据对软件信息域特性和软件复杂性的评估结果,估算软件规模。(√) &#…...

Flutter 桌面应用开发之读写Windows注册表
文章目录 需求来源Windows查询Windows版本号方法1. 如何查看Windows版本号2. Windows开发如何通过代码查询Windows版本号(1) 使用C#代码:(2) 使用VB.NET代码 3.通过注册表查看Windows版本信息 Flutter查询Windows版本号方法依赖库支持平台实现步骤1. 在pubspec.yaml…...

【Java Spring】SpringBoot 日志系统
文章目录 一、Spring Boot 日志系统1.1 Spring Boot 日志框架1.2 自定义日志打印1.3 日志级别设置1.4 日志持久化1.5 lombok 简化日志输出 一、Spring Boot 日志系统 1.1 Spring Boot 日志框架 SLF4J 和 logback都是spring boot内置的日志框架,开发者只负责调用对…...

Rust UI开发(四):iced中如何添加菜单栏(串口调试助手)
注:此文适合于对rust有一些了解的朋友 iced是一个跨平台的GUI库,用于为rust语言程序构建UI界面。 这是一个系列博文,本文是第四篇,前三篇链接: 1、Rust UI开发(一):使用iced构建UI时…...

P19 C++ 构造函数的成员初始化列表
目录 前言 01 如果不用成员列表如何初始化变量 02 成员列表初始化 03 为什么要使用成员列表初始化呢? 04 案例代码 前言 本期我们聊聊构造函数初始化列表。 你应该经常使用成员初始化列表,如果你不喜欢这种代码风格,建议你还是慢慢习惯吧…...
acwing算法基础之数学知识--Nim游戏和集合Nim游戏
目录 1 基础知识2 模板3 工程化 1 基础知识 (一) Nim游戏: n n n堆物品,每堆有 a i a_i ai个,两个玩家轮流取走任意一堆的任意个物品,但不能不取。取走最后一个物品的人获胜。 结论:如果这n…...

大数据Doris(二十八):Routine Load查看和修改作业
文章目录 Routine Load查看和修改作业 一、查看导入作业状态...

顺序表总结
📑打牌 : da pai ge的个人主页 🌤️个人专栏 : da pai ge的博客专栏 ☁️宝剑锋从磨砺出,梅花香自苦寒来 目录 🌤️arraylist的简…...

flutter 文本不随系统设置而改变大小[最全的整理]
文本不随系统设置而改变大小[四] 前言方案十九:使用LayoutBuilder和RichText方案二十:使用Transform.scale方案二十一:使用自定义文本缩放因子方案二十二:使用SingleChildScrollView方案二十三:使用FittedBox方案二十四…...

python -opencv 图像锐化
python -opencv 图像锐化 图像锐化其实,是一种增强图片对比度的技术,我们可以通过计算图像的导数,把导数绝对值数值大于零的数值加回原图像,通过这种方法,可以增强图像的对比度。 实现代码如下: import c…...

数字电源为什么一般用DSP控制,而不能用普通的单片机?
数字电源为什么一般用DSP控制,而不能用普通的单片机? 首先你要清楚,数字电源需要一个芯片具备什么功能? 1 能发PWM波 ,并且具备保护关断功能; 电源对PWM发波 要求很高,精度要ns级甚至ps级的&…...

个人投资白银收益怎么样?
个人投资白银是可以带来丰厚的收益,但收益的具体情况取决于多种因素。以下是一些明确的答案和举例,帮助投资者更好地理解个人投资白银的收益情况。 白银市场的价格波动是决定投资收益的主要因素之一,白银价格受全球经济形势、地缘局势风险、…...

代码随想录算法训练营 ---第四十五天
前言: 昨天的题做过之后,今天的题基本上都很简单,但是要注重一下细节。 第一题: 简介: 动态规划五部曲: 1.确定dp数组的含义 dp[i]:爬到有i个台阶的楼顶,有dp[i]种方法 2.确定dp…...

【密码学】【多方安全计算】不经意传输(Oblivious Transfer,OT)
文章目录 不经意传输(oblivious transfer)定义不经意传输的实例(1 out 2,二选一不经意传输)基于RSA的1 out 2 不经意传输疑问 不经意传输(oblivious transfer)定义 不经意传输(obli…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...