C++设计模式:三种工厂模式详解(简单工厂,工厂模式,抽象工厂)

news2025/1/8 6:03:48

文章目录

  • 简单工厂模式
    • 简单工厂实现步骤
    • 简单工厂优缺点
  • 工厂模式
    • 工厂模式和简单工厂模式有什么不同?
    • 工厂模式实现步骤
    • 实现代码
    • 工厂模式优缺点
  • 抽象工厂模式
    • 抽象工厂模式实现步骤
    • 实现代码
    • 抽象工厂模式优缺点

简单工厂模式

简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。

通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

简单工厂模式可以减少客户程序对类创建过程的依赖。


简单工厂实现步骤

1.提供一个工厂类

简单工厂模式的核心,它负责实现创建所有实例的内部逻辑工厂类可以被外界直接调用,创建所需的产品对象。

2.提供一个抽象产品类

简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口

3.提供一个具体产品类

简单工厂模式所创建的具体实例对象

请添加图片描述


实现代码:
我们实现一个造飞机和火箭的系统。

  1. 抽象产品类声明飞机产品和火箭产品的业务方法(纯虚函数,等待子类实现)。
  2. 具体产品类实现其父类的业务方法
  3. 具体工厂类创建产品对象:创建造飞机厂和造火箭厂
/*
造飞机造火箭
*/

/*----------------
1. 抽象产品类
----------------*/
class AbstractProduct
{
public:
	virtual ~AbstractProduct() {}
	virtual void MakeProduct() = 0;
};
/*----------------
2. 具体产品类
----------------*/

//2.1. 飞机产品类
class PlaneProduct :public AbstractProduct
{
public:
	~PlaneProduct() {}
	void MakeProduct()override
	{
		cout << "飞机产品" << endl;
	}
};
//2.2. 火箭产品类
class RocketProduct :public AbstractProduct
{
public:
	~RocketProduct() {}
	void MakeProduct()override
	{
		cout << "火箭产品" << endl;
	}
};
/*----------------
3. 具体工厂类:负责创建每一个实例产品对象
----------------*/
class Factory
{
public:
	//一个枚举,根据这个枚举的种类来决定你要创建哪个对象
	enum class ProductType { Plane, Rocket };
	static AbstractProduct* CreateProduct(ProductType type)
	{
		switch (type)
		{
		//创建飞机类
		case Factory::ProductType::Plane:
			return new PlaneProduct;
		//创建火箭类
		case Factory::ProductType::Rocket:
			return new RocketProduct;
		}
	}
};

int main()
{
	//1. 工厂创建产品
	AbstractProduct* Plane = Factory::CreateProduct(Factory::ProductType::Plane);
	//2. 使用产品
	Plane->MakeProduct();
	delete Plane;
	delete Rocket;
	
	AbstractProduct* Rocket = Factory::CreateProduct(Factory::ProductType::Rocket);
	Rocket->MakeProduct();
	delete Plane;
	delete Rocket;
	
	return 0;
}

简单工厂优缺点

优点

  • 帮助封装

    实现组件封装,面向接口编程

  • 解耦合

    客户端和具体实现类的解耦合

缺点

  • 可能增加客户端的复杂度
  • 不方便扩展子工厂

工厂模式

工厂方法模式同样属于类的创建型模式又被称为多态工厂模式 。工厂方法模式的意义是 定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。 核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色仅负责具体工厂子类 必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品

工厂模式和简单工厂模式有什么不同?

工厂方法模式与简单工厂模式的区别在结构上的并不明显。

  1. 而简单工厂模式把核心放在一个具体工厂类上。
  2. 工厂方法类的核心是一个抽象工厂类

工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口, 或者有共同的抽象父类。 当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了《“开放-封闭”原则 》 。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。工厂方法模式退化后可以演变成简单工厂模式。

在添加新产品对象时的不同:

  1. 简单工厂模式需要修改工厂方法,不符合《开放封闭原则》
  2. 工厂模式无需修改抽象工厂方法,只需添加一个具体工厂,符合《开放封闭原则》

工厂模式实现步骤

1.提供一个抽象工厂类 :所有具体工厂类的父类

2.提供与产品对应的实例工厂类:负责实例化产品对象

3.提供一个抽象产品类: 所有产品的父类

4.提供一个或多个实例产品类:工厂方法模式所创建的具体实例对象

请添加图片描述


实现代码

依旧是造飞机和火箭的例子,我们来看看它与简单工厂模式有什么不同?

  1. 抽象产品类:飞机产品与火箭产品所具有的业务方法
  2. 抽象工厂类:这是相比简单工厂模式不同的地方,把各个产品的工厂分隔开,实现一个抽象工厂,其声明了各个工厂创建对象的方法。
  3. 具体产品类
  4. 具体工厂类
#include <iostream>
using namespace std;

//造飞机造火箭

/*----------------
1. 抽象产品类
----------------*/
class AbstractProduct
{
public:
	virtual void MakeProduct() = 0;
};

/*----------------
2. 抽象工厂类
----------------*/
class AbstractFactory
{
public:
	virtual AbstractProduct* CreateProduct() = 0;
};

/*----------------
3. 具体产品类: 飞机
----------------*/
class PlaneProduct:public AbstractProduct
{
public:
	void MakeProduct()override
	{
		cout << "飞机产品" << endl;
	}
};
/*----------------
4. 具体工厂类:造飞机
----------------*/
class PlaneFactory :public AbstractFactory
{
public:
	AbstractProduct* CreateProduct()override
	{
		return new PlaneProduct;
	}
};

/*----------------
3. 具体产品类: 火箭
----------------*/
class RocketProduct :public AbstractProduct
{
public:
	void MakeProduct()override
	{
		cout << "火箭产品" << endl;
	}
};
/*----------------
4. 具体工厂类:造火箭
----------------*/
class RocketFactory :public AbstractFactory
{
public:
	AbstractProduct* CreateProduct()override
	{
		return new RocketProduct;
	}
};
int main()
{
	//1. 开设工厂(飞机,火箭)
	AbstractFactory* factory = new PlaneFactory;
	//2. 制造产品
	AbstractProduct* product =  factory->CreateProduct();
	//3. 使用产品
	product->MakeProduct();

	factory = new RocketFactory;
	product = factory->CreateProduct();
	product->MakeProduct();

	return 0;
}

工厂模式优缺点

优点

  • 需求改变时改动最小

  • 具体的创建实例过程与客户端分离

缺点:

  • 新增功能时,工程量稍大

抽象工厂模式

抽象工厂模式是所有形态的工厂模式中最为抽象和最一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。

抽象工厂方法是针对与一个产品族,使得易于交换产品系列,只需改变具体的工厂就可以使用不同的产品配置。当一个族中的产品对象被设计成一起工作且一个应用只适用同一族的对象,例如设计系统生成不同风格的UI界面,按钮,边框等UI元素在一起使用,并且只能同属于一种风格,这很容易使用抽象工厂实现。

抽象工厂模式实现步骤

  1. 提供一个抽象工厂类:声明一组创建一族产品的工厂方法
  2. 提供一个具体工厂类:实现了在抽象工厂创建产品的工厂方法
  3. 提供一个抽象产品类:抽象产品中声明了产品具有的业务方法
  4. (可选)提供抽象产品族:抽象产品族表示了某些不同族的产品类型(键盘,鼠标…)
  5. 提供一个具体产品类:实现抽象产品接口中声明的业务方法
    请添加图片描述

实现代码

#include <iostream>
using namespace std;
/*
抽象工厂模式
1. 抽象产品类
2. 抽象产品族
3. 具体产品类
4. 抽象工厂类
5. 具体工厂类
*/

//----生产键盘和鼠标----

//抽象产品类: 声明了产品具有的业务方法
class AbstractProduct
{
public:
	virtual ~AbstractProduct() {}
	virtual void MakeProduct() = 0;
};

//1. 键盘
//抽象产品族
class KeyBoard :public AbstractProduct {};

//具体产品类:实现产品的具体方法
class LogiKeyBoard :public KeyBoard
{
public:
	~LogiKeyBoard() {}
	void MakeProduct()override
	{
		cout << "罗技键盘" << endl;
	}
};
class RazerKeyBoard :public KeyBoard
{
public:
	~RazerKeyBoard() {}
	void MakeProduct()override
	{
		cout << "雷蛇键盘" << endl;
	}
};

//2. 鼠标
//抽象产品族
class Mouse :public AbstractProduct {};

//具体产品类
class LogiMouse :public Mouse
{
public:
	~LogiMouse() {}
	void MakeProduct()override
	{
		cout << "罗技鼠标" << endl;
	}
};
class RazerMouse :public Mouse
{
public:
	~RazerMouse() {}
	void MakeProduct()override
	{
		cout << "雷蛇鼠标" << endl;
	}
};

/*
//TODO:在此增加新的产品族与具体产品类...
//
//*/

//抽象工厂类: 声明提供创建每一族产品的方法
class AbstractFactory
{
public:
	virtual ~AbstractFactory() {}
	virtual KeyBoard* CreateKeyBoard() = 0;
	virtual Mouse* CreateMouse() = 0;
	//TODO: 提供每一个产品族的创建方法...
};

//具体工厂类:实现创建产品的方法
//1. 罗技工厂
class LogiFactory:public AbstractFactory
{
public:
	~LogiFactory() {}
	KeyBoard* CreateKeyBoard()override
	{
		return new LogiKeyBoard;
	}
	Mouse* CreateMouse()override
	{
		return new LogiMouse;
	}
};
//2. 雷蛇工厂
class RazerFactory :public AbstractFactory
{
public:
	~RazerFactory() {}
	KeyBoard* CreateKeyBoard()override
	{
		return new RazerKeyBoard;
	}
	Mouse* CreateMouse()override
	{
		return new RazerMouse;
	}
};

int main()
{
	AbstractFactory* Factory = new RazerFactory;
	KeyBoard* keyBoard =  Factory->CreateKeyBoard();
	Mouse* mouse =  Factory->CreateMouse();
	keyBoard->MakeProduct();
	mouse->MakeProduct();

	delete Factory;
	delete keyBoard;
	delete mouse;
	
	Factory = new LogiFactory;
	keyBoard = Factory->CreateKeyBoard();
	mouse = Factory->CreateMouse();
	keyBoard->MakeProduct();
	mouse->MakeProduct();

	delete Factory;
	delete keyBoard;
	delete mouse;
	Factory = nullptr;
	keyBoard = nullptr;
	mouse = nullptr;
	return 0;
}

抽象工厂模式优缺点

优点

  • 抽象工厂封装了变化,封装了对象创建的具体细节
  • 增加新的产品族很方便,无须修改已有系统
  • 针对接口进行编程而不是针对具体进行编程

缺点:

  • 增加新的产品等级结构需对原系统做较大修改(违背开放封闭)

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

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

相关文章

【算法】算法分析技术(第一章习题解答)

1 算法分析技术 1.1 假设 fff 和 ggg 是定义在自然数集合上的函数, 若对某个其他函数 hhh 有 fO(h)f O(h)fO(h)和 gO(h)g O(h)gO(h) 成立, 那么证明 fgO(h)f g O(h)fgO(h) 证明&#xff1a; 根据已知条件 fO(h)f O(h)fO(h)&#xff0c;存在 c1>0c_{1}>0c1​>0 …

错题记录2:源码补码二进制转换

补码原码二进制一直是本人比较头疼的问题&#xff0c;今日找题目来做发现还是错得多&#xff0c;记录以下&#xff0c;再回顾一遍。 1.如下代码输出的是什么&#xff08; &#xff09; char a101; int sum200; a27;suma; printf("%d\n",sum); A: 327 B: 99 C: 3…

【MySQL】详解MySQL数据库事务

MySQL数据库事务数据库事务特性事务的并发问题事务的隔离级别分布式事务解决方案1.XA 协议2.TCC3.消息一致性方案4.阿里云中的全局事务服务 GTS数据库事务特性 数据库事务具备ACID四大特性&#xff1a; 原子性&#xff1a;是指事务操作时具备原子操作的&#xff0c;就是说整…

分布式系统架构

分布式系统定义 分布式系统&#xff1a;硬件或软件组件分布在不同的网络计算机上&#xff0c;彼此之间仅仅通过消息传递进行通信和协调的系统。 为什么需要分布式系统 提升系统吞吐量&#xff1a;集群协同解决单机性能瓶颈提高系统可用性 &#xff1a;冗余部署&#xff0c;各…

OSS阿里云存储

一、开通“对象存储OSS”服务 2、进入管理控制台 二、控制台使用 点击Buket列名&#xff0c;Buket可以看作是一系列的虚拟内存空间它是一个独立的小个体 创建mystudent 创建成功后就有下面的样子了 &#xff0c;创建的时候读写权限&#xff0c;我们选择公共读&#xff0c…

matlab中sign函数的使用(提取符号)

仅用于记录自己学习过程中遇到的函数 matlab中sign函数的使用&#xff0c;提取符号 一、语法 Y sign(x) 返回与 x 大小相同的数组 Y&#xff0c;其中 Y 的每个元素是&#xff1a; 1&#xff0c;前提是 x 的对应元素大于 0。 0&#xff0c;前提是 x 的对应元素等于 0。 -1&am…

CAP定理与分布式事务理论

文章目录一、CAP定理1.1 一致性1.2 可用性1.3 分区容错1.4 定理的矛盾点二、分布式事务理论2.1 BASE理论2.2 解决分布式事务思路一、CAP定理 分布式系统有三个指标。 Consistency&#xff08;一致性&#xff09;Availability&#xff08;可用性&#xff09;Partition toleranc…

GBASE斩获2022科技赋能金融业数字化转型突出贡献奖

12月27日&#xff0c;由中国人民银行主管的《金融电子化》杂志社主办的“2022中国金融科技年会暨第十三届金融科技应用创新奖颁奖典礼”成功举办&#xff0c;在本次活动上&#xff0c;GBASE南大通用“多模多态分布式数据库GBase 8c”&#xff0c;荣获“2022科技赋能金融业数字化…

PyCharm高级配置

pycharm设置内存大小步骤1&#xff0c;Help -> FindAction -> (输入 “VM”) -> (点击)“Edit Custom VM options”2&#xff0c;Pycharm会在编辑器中打开适当的vmoptions文件&#xff08;pycharm.vmoptions或pycharm64.options&#xff09;。3&#xff0c;将**-Xms**…

CCIE重认证350-401

拖图题 QoS traffic policing: causes TCP retransmissions when traffic is dropped导致TCP重传时流量下降 introduces no delay and jitter引入无延迟和抖动 drops excessive traffic减少过多的流量 traffic shaping: buffers excessive traffic缓冲过多的流量 introduce…

Sensor+ISP专栏-Demosaic

SensorISP专栏-Demosaic 1.what is raw raw图指的是从cmos sensor直接输出的原始图像&#xff0c;它本身没有颜色分量。在CMOS Sensor中使用彩色滤镜阵列(color filter array&#xff0c;CFA) 的方式捕获彩色图像&#xff0c;每个感光像素的上面覆盖一个语物理像素相同面积大…

OpenStack-Mitaka版本部署

1.环境准备 centos7.2相关文件 镜像&#xff1a;https://mirrors.aliyun.com/centos-vault/7.2.1511/isos/x86_64/CentOS-7-x86_64-DVD-1511.iso?spma2c6h.25603864.0.0.5c565932JYniuU openstack-mitaka rpm包&#xff1a;https://mirrors.aliyun.com/centos-vault/7.2.15…

hadoop 3.x 案例7: hadoop大数据平台日志

文章目录一. Hadoop日志1.1 namenode日志1.2 datanode日志1.3 secondarynamenode日志1.4 yarn日志1.4.1 resourcemanger日志1.4.2 nodemanager日志1.5 historyServer日志二. Hive日志三. Spark日志四. Flink日志一. Hadoop日志 cd $HADOOP_HOME/logs日志分类: namenode日志 d…

【ROS】—— ROS通信机制进阶(七)

文章目录前言1. 常用API(C)1.1 初始化1.2 话题与服务相关对象1.3 回旋函数(重点)1.4 时间1.4.1 获取当前时刻and指定时刻1.4.2 持续时间1.4.3 时间运算1.4.4 设置运行频率1.4.5 定时器1.5 其他函数2. 常用API(python)2.1 初始化2.2 话题与服务相关对象2.3 回旋函数2.4 时间2.4.…

Bandit算法学习[网站优化]02——epsilon-Greedy 算法

Bandit算法学习[网站优化]02——epsilon-Greedy 算法 参考资料 White J. Bandit algorithms for website optimization[M]. " O’Reilly Media, Inc.", 2013.https://github.com/johnmyleswhite/BanditsBook 实验环境&#xff1a;jupyter python 3.7 项目地址&am…

twrp Xposed zip包脚本定制全解析

声明:本文不对印刷机导致的任何结果承担责任,请谨慎尝试 想要研究一个新技术,最好的办法就是read the fuck source code,读源码时最直接高效的方式,当然,这很难啃,所以通常也可以配合网上一些教程来理解,但是通常,值钱的技术一般人是不会在网上发布的,因为技术的价值就…

大厂必备Stream流、方法引用的使用

大厂必备Stream流、方法引用的使用 1 Stream的基本使用 1.1 思想 当需要对多个元素进行操作&#xff08;特别是多步操作&#xff09;的时候&#xff0c;考虑到性能及便利性&#xff0c;我们应该首先拼好一个“模型”步骤方案&#xff0c;然后再按照方案去执行它。【流水线】 …

spring源码-容器refresh

spring源码 铺垫 1.xml信息封装 我们可以预测的大致顺序 xml里的bean 封装成对象定义信息更容易进一步的 创建 注入 BeanDefinition的属性&#xff1a;可以看出是对xml里信息的封装 public interface BeanDefinitionReader 定义规范2.使用反射 为什么不用new创建对象&#x…

NXP EMDA学习(1):TCD寄存器详解

eDMA(Enhanced DMA)即增强型DMA&#xff0c;它是NXP芯片中独有的功能&#xff0c;其最重要的一个特性也是eDMA的核心就是TCD(Transfer Control Descriptor)即传输控制描述符。所以&#xff0c;我们就来看一下这个结构体中各个字段的内容的含义&#xff0c;对这些字段有一个基础…

位置检测有哪些传感器可以用?(带磁编码器AS5600代码)

常见的有三种 编码器、霍尔传感器、磁传感器。 编码器一般指AB相正交脉冲的增量器件&#xff0c;有的还会有一个Z相信号&#xff0c;用来指示零位&#xff1b; 霍尔传感器一般是指ABC三个成120度角度间隔排列的器件&#xff0c;这种传感器一般集成在电机内部&#xff0c;电机…