【16】c++设计模式——>建造者(生成器)模式

news2025/1/21 6:01:38

什么是建造者模式?

建造者模式(Builder Pattern)是一种创建型设计模式,它允许你构造复杂对象步骤分解。你可以不同的步骤中使用不同的方式创建对象,且对象的创建与表示是分离的。这样,同样的构建过程可以创建不同的表示。
在 C++ 中,建造者模式通常涉及到以下几个关键部分:
1.产品(Product):这是最终要构造的对象。它通常包含很多属性。
2.抽象建造者(Abstract Builder):这是一个接口,定义了创建产品所需的各个步骤的方法。
3.具体建造者(Concrete Builder):这是实现抽象建造者接口的具体类。它实现了创建产品所需的各个步骤。
4.导演(Director):这个类负责执行创建产品的整个过程。它使用具体建造者来创建产品的各个部分,并在适当的时候调用它们。

建造者模式和工厂模式的区别?

建造者模式和工厂模式都是创建型设计模式,但它们的关注点和用途有所不同。以下是它们的主要区别:
1.关注点建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程
2.创建对象的力度:建造者模式创建复杂的对象,由各种复杂的部件组成,而工厂模式创建出来的对象都一样。
3.顺序:建造者模式根据建造过程中的顺序不一样,最终的对象部件组成也不一样。而工厂模式则没有这样的关注。
4.使用场景:创建简单对象时,通常使用工厂模式;创建复杂对象时,可以考虑使用建造者模式。
总的来说,工厂模式更注重对象的创建,而建造者模式更注重对象的组装过程和组成部分。在实际应用中,可以根据需要选择使用哪种设计模式。

建造者模式适用什么场景,举个具体的例子

建造者模式适用于创建具有多个组成部分的复杂对象,尤其是那些需要对个步骤来创建的对象。
假设我们需要创建一个复杂的“电脑”对象,该对象包含多个组成部分,如“CPU”、“内存”、“硬盘”等。我们可以使用建造者模式来创建这个对象,具体步骤如下:
1.首先我们需要一个产品类Computer ,也就是电脑,这是最终要构造的对象,电脑通常包含很多属性也就是组成部分,比如CPU,内存,硬盘这些;例如,在具体电脑建造者中,我们可以调用“Computer”类的“setCPU()”、“setMemory()”和“setHardDisk()”方法来设置电脑的各个组成部分
2.然后,我们定义一个抽象建造者ComputerBuilder接口,该接口定义了创建电脑对象所需的各个步骤的虚方法。如“buildCPU()”、“buildMemory()”、“buildHardDisk()”等。
3.接下来,我们定义一个具体建造者ConcreteComputerBuilder类,该类实现了抽象建造者接口中定义的所有方法。在具体建造者中,我们可以按照需要的顺序和方式来创建电脑对象的各个组成部分。
4.然后,我们定义一个导演ComputerDirector类,该类负责执行创建电脑对象的整个过程。导演类中使用具体建造者来创建电脑对象的各个部分,并在适当的时候调用它们。
5.最后,客户端代码可以使用导演类来创建电脑对象。客户端不需要知道电脑对象内部的具体实现细节,只需要调用导演类提供的方法即可。
代码示例:

#include<iostream>
#include<string>
using namespace std;

//1.产品:电脑
class Computer
{
public:
	void setCPU(string cpu) { m_cpu = cpu; }
	void setMemory(string memory) { m_memory = memory; }
	void setHardDisk(string hardDisk) { m_hardDisk = hardDisk; }
	//const位于函数参数列表之后,表示该函数是一个常量成员函数,该函数不会修改任何成员变量的值
	void print()const {   
		std::cout << "CPU: " << m_cpu << ", Memory: " << m_memory << ", Hard Disk: " << m_hardDisk << std::endl;
	}
private:
	string m_cpu;
	string m_memory;
	string m_hardDisk;
};
//2.抽象建造者:电脑建造者接口
class ComputerBuilder
{
public:
	virtual ~ComputerBuilder() {}; //虚析构,为了销毁父类指针所指向的子类对象
	virtual void buildCPU() = 0; 
	virtual void buildMemory() = 0;
	virtual void buildHardDisk() = 0;
	virtual Computer* getComputer() = 0;
};
//3.具体建造者:具体的电脑建造者
class  ConcreteComputerBuilder :public ComputerBuilder
{
public:
	void buildCPU() { m_computer->setCPU("Intel Core i7"); }
	void buildMemory() { m_computer->setMemory("16GB DDR4");}
	void buildHardDisk() { m_computer->setHardDisk("1TB SSD");}
	Computer* getComputer() { return m_computer; }

private:
	Computer* m_computer = new Computer;
};
//4.导演:电脑建造导演
class ComputerDirector
{
public:
	ComputerDirector(ComputerBuilder* builder) :m_builder(builder) {}
	void construct() {
		m_builder->buildCPU();
		m_builder->buildMemory();
		m_builder->buildHardDisk();
	}
private:
	ComputerBuilder* m_builder;
};
int main()
{
	ConcreteComputerBuilder builder;//创建一个具体的电脑对象
	ComputerDirector director(&builder); //创建一个导演
	director.construct();
	builder.getComputer()->print();

	delete builder.getComputer();
	return 0;
}

在这里插入图片描述

手机生产

我现在要生产iphone手机,有iPhone14和iPhone15,各自又有mini和pro两个版本。

#include <iostream>
#include <memory>

//产品类:iphone
class iPhone
{
public:
	void setMemory(const std::string& memory) { m_memory = memory; }
	void setScreen(const std::string& screen) { m_screen = screen; }
	void setAppearance(const std::string& apperance) { m_appearance = apperance; }
	void showInfo() const {
		std::cout << "Memory: " << m_memory << std::endl;
		std::cout << "Screen: " << m_screen << std::endl;
		std::cout << "Appearance: " << m_appearance << std::endl;
	}
private:
	std::string m_memory;
	std::string m_screen;
	std::string m_appearance;
};
//抽象建造者:iphone手机建造者接口
class iPhoneBuilder
{
public:
	virtual void buildMemory() = 0;
	virtual void buildScreen() = 0;
	virtual void buildAppearance() = 0;
	virtual std::unique_ptr<iPhone> getiPhone() = 0;

};
//具体建造者:iPhone14 Mini 建造者
class iPhoneBuilder14Mini :public iPhoneBuilder
{
	void buildMemory() { m_memory = "64GB"; }
	void buildScreen() { m_screen = "5.4-inch"; }
	void buildAppearance() { m_appearance = "Glass back and aluminum frame"; };
	std::unique_ptr<iPhone>  getiPhone() override
	{
		  std::unique_ptr<iPhone> iphone = std::make_unique<iPhone>();
		  iphone->setMemory(m_memory);
		  iphone->setScreen(m_screen);
		  iphone->setAppearance(m_appearance);
		  return iphone;
	}

private:
	std::string m_memory;
	std::string m_screen;
	std::string m_appearance;
};

//具体建造者:iPhone14 pro 建造者
class iPhoneBuilder14PRO :public iPhoneBuilder
{
	void buildMemory() { m_memory = "256GB"; }
	void buildScreen() { m_screen = "6.1-inch"; }
	void buildAppearance() { m_appearance = "Ceramic back and stainless steel frame"; };
	std::unique_ptr<iPhone>  getiPhone() override
	{
		std::unique_ptr<iPhone> iphone = std::make_unique<iPhone>();
		iphone->setMemory(m_memory);
		iphone->setScreen(m_screen);
		iphone->setAppearance(m_appearance);
		return iphone;
	}
private:
	std::string m_memory;
	std::string m_screen;
	std::string m_appearance;
};

//导演类:生成手机
class Director 
{
public:
	std::unique_ptr<iPhone> create(iPhoneBuilder& builder)
	{
		builder.buildMemory();
		builder.buildScreen();
		builder.buildAppearance();
		return builder.getiPhone();
	}
};
int main()
{
	Director director;
	
	//iphone14 mini
	iPhoneBuilder14Mini iphone14mini;
	std::unique_ptr<iPhone> mini = director.create(iphone14mini);
	std::cout << "iPhone 14 Mini" << std::endl;
	mini->showInfo();
	std::cout << std::endl;

	iPhoneBuilder14PRO iphone14PRO;
	std::unique_ptr<iPhone> pro = director.create(iphone14PRO);
	std::cout << "iPhone 14 Mini" << std::endl;
	pro->showInfo();
	std::cout << std::endl;
}

在这里插入图片描述

sunny和merry号生产

现在我们开始着手把路飞的海贼船桑尼号 和梅利号使用生成器模式键造出来。
1、一共需要三个生成器类,一共父类,两个子类;
2、父类可以是一个抽象类,提供的建造函数都是虚函数;
3、在两个生成器子类中,使用建造函数分别将桑尼号 和梅利号各个零部件造出来。
如果我们仔细分析,发现还需要解决另外一个问题,通过生成器得到了海贼船的各个零部件,这些零部件必须有一个载体,那就是海贼船对象。因此,还需要提供一个或多个海贼船类。
因为桑尼号 和梅利号这两艘的差别非常之巨大,所以我们定义两个海贼船类,代码如下:

#include <iostream>
#include <memory>
#include <map>
#include <vector>
#include <string>
using namespace std;

/*******************************_两个船类(Sunny号和Merry号)_*************************************/
//产品1:Sunny号
class Sunnyship
{
public:
	//添加零件
	void addParts(string name)
	{
		m_parts.push_back(name);
	}
	void showParts()
	{
		for (const auto& item : m_parts)
		{
			cout << item << " ";
			cout << endl;
		}
	}
private:
	vector<string> m_parts;
};
//产品2:Merry号
class Merryship
{
public:
	//添加零件
	void assemble(string name,string parts)
	{
		m_parts.insert(make_pair(name,parts));
	}
	void showParts()
	{
		for (const auto& item : m_parts)
		{
			cout << item.first << ": "<<item.second << " ";
			cout << endl;
		}
	}
private:
	map<string,string> m_parts;
};
/**************************************************************************************************/
/*****************************************_生成器类_*********************************************************/
//抽象生成器类
class ShipBuilder
{
public:
	virtual void reset() = 0;
	virtual void buildBody() = 0;
	virtual void buildWeapon() = 0;
	virtual void buildEngine() = 0;
	virtual void buildInterior() = 0;
	virtual ~ShipBuilder() {}
};
//具体生成器类:Sunny号生成器
class SunnyBuilder :public ShipBuilder
{
public:
	SunnyBuilder()
	{
		reset();
	}
	~SunnyBuilder()
	{
		if (m_sunny != nullptr)
		{
			delete m_sunny;
		}
	}
	void reset() override
	{
		m_sunny = new Sunnyship;
	}

	void buildBody()
	{
		m_sunny->addParts("神树亚当的树干");
	}
	void buildWeapon()
	{
		m_sunny->addParts("狮吼炮");
	}
	void buildEngine()
	{
		m_sunny->addParts("可乐驱动");
	}
	void buildInterior()
	{
		m_sunny->addParts("豪华精装修的内饰");
	}
	Sunnyship* getSunny()
	{
		Sunnyship* ship = m_sunny;
		m_sunny = nullptr;
		return ship;
	}

private:
	Sunnyship* m_sunny = nullptr;
};
//具体生成器类:Merry号生成器
class MerryBuilder :public ShipBuilder
{
public:
	MerryBuilder()
	{
		reset();
	}
	~MerryBuilder()
	{
		if (m_merry != nullptr)
		{
			delete m_merry;
		}
	}
	void reset() override
	{
		m_merry = new class Merryship;
	}

	void buildBody()
	{
		m_merry->assemble("船体","优质木材");
	}
	void buildWeapon()
	{
		m_merry->assemble("武器","四门大炮");
	}
	void buildEngine()
	{
		m_merry->assemble("动力","蒸汽机");
	}
	void buildInterior()
	{
		m_merry->assemble("内饰","精装修");
	}
	Merryship* getMerry()
	{
		Merryship* ship = m_merry;
		m_merry = nullptr;
		return ship;
	}

private:
	Merryship* m_merry = nullptr;
};
/******************************************_导演类_***********************************************/
class Director
{
public:
	void setBuilder(ShipBuilder* builder)
	{
		m_builder = builder;
	}
	void builderSimpleShip()
	{
		m_builder->buildBody();
		m_builder->buildEngine();
	}

	void builderStandShip()
	{
		builderSimpleShip();
		m_builder->buildWeapon();
	}

	void builderRegalShip()
	{
		builderStandShip();
		m_builder->buildInterior();
	}
private:
	ShipBuilder* m_builder = nullptr;
};
/*******************************_代码测试_**************************************************/
//建造Sunny号
void buildSunny()
{
	Director director;
	SunnyBuilder Sbuild;
	//简约型
	director.setBuilder(&Sbuild);
	director.builderSimpleShip();
	Sunnyship* Sship = Sbuild.getSunny();
	Sship->showParts();
	delete Sship;

}
int main()
{
	buildSunny();
}

在这里插入图片描述

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

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

相关文章

python pygame入门 - 安装测试篇

pygame入门 - 安装篇 引言一、安装测试1.1 创建虚拟环境1.2 安装测试pygame 二、查看例程源码2.1 源码位置2.2 简单修改 引言 pygame是Python语言特别为游戏开发而设计的一个开源库。它提供了一系列模块和函数&#xff0c;可以帮助开发者快速构建2D游戏、多媒体应用程序和其他…

Electronjs入门-Electron中的主要模块

在本节中&#xff0c;我们将了解在Electron中创建任何应用程序时的一些基本模块&#xff1b;这些模块多种多样&#xff0c;使我们能够轻松地进行进程通信&#xff0c;创建操作系统的本地菜单。 为了利用Electron模块&#xff0c;以及任何第三方或Node模块&#xff0c;不仅在主流…

10.3倒水问题(几何图论建模)

坐标图中每一个位置都对应一个合法的状态&#xff0c;BC对5升杯子做出限制&#xff0c;AD对9升杯子作出限制 每次倒水&#xff0c;都只能把目标杯子装满&#xff0c;否则无法确定倒出水的多少与目标杯子此时水的容量 所以例如&#xff0c;倒5升杯子时&#xff0c;只能要么把5…

盘点网安最好入手的10大岗位,就业转行必看

前言 前段时间&#xff0c;知名机构麦可思研究院发布了《2022年中国本科生就业报告》&#xff0c;其中详细列出近五年的本科绿牌专业&#xff0c;信息安全位列第一。 对于网络安全的发展与就业前景已经说过很多&#xff0c;它是收入较高的岗位之一&#xff0c;在转行领域也占…

IO流 之 打印流( PrintStream 和 PrintWriter )

打印流可以实现更加方便的打印数据出去&#xff0c;可以实现打印啥就是啥 PrintStream字节打印流 代码演示&#xff0c;将字符串和其他类型&#xff0c;打印到f.txt文件中。 package day0927;import java.io.FileNotFoundException; import java.io.PrintStream; import java…

伟大不能被计划

假期清理书单&#xff0c;把这个书读完了&#xff0c;结果发现出奇的好&#xff0c;可以说是值得亲身去读的书&#xff0c;中间的一些论述提供了人工智能专业方面的视角来论证这这个通识观点&#xff0c;可信度很不错&#xff1b; 这篇blog也不是对书的总结&#xff0c;更多的是…

LLMs 奖励剥削 RLHF: Reward hacking

让我们回顾一下你到目前为止所学到的内容。RLHF是一个微调过程&#xff0c;用于使LLM与人类偏好保持一致。在这个过程中&#xff0c;您利用奖励模型来评估LLM对提示数据集的完成情况&#xff0c;根据人类偏好指标&#xff08;如有帮助或无帮助&#xff09;进行评估。 接下来&…

软件设计开发笔记6:基于QT的Modbus RTU从站

Modbus是一种常见的工业系统通讯协议。在我们的设计开发工作中经常使用到它。作为一种主从协议&#xff0c;在上一篇我们实现了Mobus RTU主站工具&#xff0c;接下来这一篇中我们将简单实现一个基于QT的Mobus RTU从站工具。 1、概述 Modbus RTU从站应用很常见&#xff0c;有一…

山西电力市场日前价格预测【2023-10-07】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-10-07&#xff09;山西电力市场全天平均日前电价为422.87元/MWh。其中&#xff0c;最高日前电价为1500.00元/MWh&#xff0c;预计出现在18: 15-18: 45。最低日前电价为221.56元/MWh&#x…

【JavaEE】_HTTP请求与HTTP响应

目录 1. HTTP协议 2. HTTP请求 2.1 HTTP请求首行 2.2 URL 2.3 HTTP方法 2.3.1 GET请求 2.3.2 POST请求 2.3.3 GET与POST的区别 2.3.4 其他方法 2.4 请求报头header 2.4.1 Host&#xff1a; 2.4.2 Content-Length与Content-Type&#xff1a; 2.4.3 User-Agent&…

JavaScript系列从入门到精通系列第十七篇:JavaScript中的全局作用域

文章目录 前言 1&#xff1a;什么叫作用域 一&#xff1a;全局作用域 1&#xff1a;全局变量的声明 2&#xff1a;变量声明和使用的顺序 3&#xff1a;方法声明和使用的顺序 前言 1&#xff1a;什么叫作用域 可以起作用的范围 function fun(){var a 1; } fun();consol…

练[ZJCTF 2019]NiZhuanSiWei

[ZJCTF 2019]NiZhuanSiWei 文章目录 [ZJCTF 2019]NiZhuanSiWei掌握知识解题思路代码分析1代码分析2 关键paylaod 掌握知识 ​ data伪协议和php伪协议的使用&#xff0c;反序列化&#xff0c;代码审计&#xff0c;文件包含,file_get_contents函数绕过 解题思路 打开题目链接&…

【计算机操作系统慕课版】第二章:进程的控制与描述

注&#xff1a;博主斥巨资买到了2021版本慕课版的pdf 如果需要的话可以来私聊我哦~ 操作系统第二章知识点目录&#xff1a; 一、前言&#xff1a;前驱图与程序执行 1.1前驱图&#xff08;看箭头就行&#xff0c;名字高级&#xff0c;底层简单&#xff09; 1.2程序顺序执行 1…

Umijs介绍

今天我们来看 umijs 我们访问官网 https://umijs.org/ 这是一个可 插拔的企业级 React框架 当然 你也可以选择 React 的一个脚手架 但是 这样就有很多需要考虑的东西 用这个umi 很多点 我们就不需要考虑了 框架已经帮我们配置好了 这边 我们点击快速上手的一个 指南 我们可…

vue-img-cutter 实现图片裁剪[vue 组件库]

借助 vue-img-cutter 可以在网页端实现图片裁剪功能&#xff0c;最终功能效果如下&#xff1a; 组件 npm 安装 npm install vue-img-cutter2 --save-dev # for vue2 npm install vue-img-cutter3 --save-dev # for vue3vue-img-cutter使用 template模板标签模块&#xff0c…

用Python操作MySQL教程!干货满满!

python操作数据库介绍 Python 标准数据库接口为 Python DB-API&#xff0c;Python DB-API为开发人员提供了数据库应用编程接口。Python 数据库接口支持非常多的数据库&#xff0c;你可以选择适合你项目的数据库&#xff1a; GadFly mSQL MySQL PostgreSQL Microsoft SQL S…

Spring基础以及核心概念(IoC和DIQ)

1.Spring是什么 Spring是包含了众多工具方法的IoC容器 2.loC&#xff08;Inversion of Control &#xff09;是什么 IoC:控制反转,Spring是一个控制反转容器(控制反转对象的生命周期) Spring是一个loC容器&#xff0c;我们之前学过的List/Map就是数据存储的容器&#xff0c;to…

大数据Doris(五):开始编译 Doris

文章目录 开始编译 Doris 一、下载Doris的安装包 二、解压缩 三、上传配置文件

linux常见命令以及jdk,tomcat环境搭建

目录 Is pwd cd touch cat echo vim 复制粘贴 mkdir rm cp jdk部署 1. yum list | grep jdk进行查找​编辑 2.安装​编辑 3.再次确认 4.判断是否安装成功 tomcat安装 1.下载压缩包&#xff0c;把压缩包上传至linux(可能需要yum install lrzsz) 2.解压缩unzip 压缩包名&…