《设计模式》工厂模式
《设计模式》工厂模式
工厂模式又分为简单工厂(Simple Factory)、工厂方法(Factory Method)和抽象工厂(Abstract Factory)都是常用的创建型设计模式,它们的主要区别如下:
- 简单工厂:由一个工厂类根据传入的参数来决定创建哪一种产品类的对象。简单工厂适用于对象的创建比较简单,且客户端只需要知道传入的参数即可获取相应的对象的场景。
- 工厂方法:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法模式适用于需要一组相关对象的场景,客户端不需要知道它所使用的对象的具体类型,只需要知道创建对象的接口即可。
- 抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。抽象工厂模式适用于需要一组相关的对象,这些对象之间有相互依赖关系,客户端不需要知道创建对象的具体实现细节,只需要知道创建对象的接口即可。
这三种工厂模式的优点及使用场景如下:
- 简单工厂的优点:易于实现、客户端调用方便。适用于工厂类负责创建的对象比较少的场景。
- 工厂方法的优点:符合开闭原则、可扩展性强。适用于需要一组相关对象,并且需要灵活地增加、替换和删除对象的场景。
- 抽象工厂的优点:符合开闭原则、封装性好、可扩展性强。适用于需要创建一组相互依赖、相关或不同类型的对象的场景。
综上所述,选择哪种工厂模式取决于具体的需求场景。如果只需要创建一种对象,则可以使用简单工厂;如果需要创建一组相关的对象,并且需要灵活地增加、替换和删除对象,则可以使用工厂方法;如果需要创建一组相互依赖、相关或不同类型的对象,则可以使用抽象工厂。
简单工厂
首先,定义一个抽象产品类 Product,它是由简单工厂模式负责创建的对象:
class Product {
public:virtual ~Product() {}virtual void operation() = 0;
};
接下来,定义具体产品类 ConcreteProductA 和 ConcreteProductB:
class ConcreteProductA : public Product {
public:void operation() {std::cout << "ConcreteProductA::operation()" << std::endl;}
};class ConcreteProductB : public Product {
public:void operation() {std::cout << "ConcreteProductB::operation()" << std::endl;}
};
这两个类继承了抽象产品类 Product,并实现了 operation 函数。ConcreteProductA 和 ConcreteProductB 是简单工厂模式创建的具体对象。
接下来,定义一个工厂类 Factory,它负责创建具体产品的对象:
class Factory {
public:Product* create_product(int type) {switch (type) {case 0:return new ConcreteProductA();case 1:return new ConcreteProductB();default:return nullptr;}}
};
这个工厂类有一个 create_product 函数,根据传入的类型返回具体产品的对象。在这个示例中,我们使用 switch 语句根据类型选择创建哪种具体产品。
最后,我们可以在主函数中使用简单工厂模式创建具体产品的对象:
int main() {Factory factory;Product* productA = factory.create_product(0);if (productA) {productA->operation();delete productA;}Product* productB = factory.create_product(1);if (productB) {productB->operation();delete productB;}Product* productC = factory.create_product(2);if (!productC) {std::cout << "Invalid product type!" << std::endl;}return 0;
}
在主函数中,我们先创建一个工厂对象,然后分别使用它创建 ConcreteProductA 和 ConcreteProductB 的对象,并调用它们的 operation 函数进行操作。最后,我们试图使用一个不存在的类型创建产品,这时候工厂类将返回 nullptr。
以上就是用 C++ 实现简单工厂模式的示例。
工厂方法
首先,定义一个抽象产品类 Product,它是由工厂方法模式负责创建的对象:
class Product {
public:virtual ~Product() {}virtual void operation() = 0;
};
接下来,定义具体产品类 ConcreteProductA 和 ConcreteProductB:
class ConcreteProductA : public Product {
public:void operation() {std::cout << "ConcreteProductA::operation()" << std::endl;}
};class ConcreteProductB : public Product {
public:void operation() {std::cout << "ConcreteProductB::operation()" << std::endl;}
};
这两个类继承了抽象产品类 Product,并实现了 operation 函数。ConcreteProductA 和 ConcreteProductB 是工厂方法模式创建的具体对象。
接下来,定义一个抽象工厂类 Factory,它声明一个工厂方法 create_product,由具体工厂类负责实现这个方法:
class Factory {
public:virtual ~Factory() {}virtual Product* create_product() = 0;
};
具体工厂类继承这个抽象工厂类,并实现 create_product 方法,用于创建具体产品的对象:
class ConcreteFactoryA : public Factory {
public:Product* create_product() {return new ConcreteProductA();}
};class ConcreteFactoryB : public Factory {
public:Product* create_product() {return new ConcreteProductB();}
};
这两个类继承了抽象工厂类 Factory,并实现了 create_product 方法。ConcreteFactoryA 和 ConcreteFactoryB 是工厂方法模式创建的具体工厂。
最后,我们可以在主函数中使用工厂方法模式创建具体产品的对象:
int main() {Factory* factoryA = new ConcreteFactoryA();Product* productA = factoryA->create_product();if (productA) {productA->operation();delete productA;}delete factoryA;Factory* factoryB = new ConcreteFactoryB();Product* productB = factoryB->create_product();if (productB) {productB->operation();delete productB;}delete factoryB;return 0;
}
在主函数中,我们先创建一个 ConcreteFactoryA 对象,然后使用它创建 ConcreteProductA 的对象,并调用它的 operation 函数进行操作。然后我们创建一个 ConcreteFactoryB 对象,使用它创建 ConcreteProductB 的对象,并调用它的 operation 函数进行操作。最后,我们删除创建的对象并销毁工厂对象。
以上就是用 C++ 实现工厂方法模式的示例。
抽象工厂
首先,定义一个抽象产品类 AbstractProductA 和 AbstractProductB,它们是由抽象工厂模式负责创建的对象:
class AbstractProductA {
public:virtual ~AbstractProductA() {}virtual void operationA() = 0;
};class AbstractProductB {
public:virtual ~AbstractProductB() {}virtual void operationB() = 0;
};
接下来,定义具体产品类 ConcreteProductA1、ConcreteProductA2、ConcreteProductB1 和 ConcreteProductB2:
class ConcreteProductA1 : public AbstractProductA {
public:void operationA() {std::cout << "ConcreteProductA1::operationA()" << std::endl;}
};class ConcreteProductA2 : public AbstractProductA {
public:void operationA() {std::cout << "ConcreteProductA2::operationA()" << std::endl;}
};class ConcreteProductB1 : public AbstractProductB {
public:void operationB() {std::cout << "ConcreteProductB1::operationB()" << std::endl;}
};class ConcreteProductB2 : public AbstractProductB {
public:void operationB() {std::cout << "ConcreteProductB2::operationB()" << std::endl;}
};
这四个类继承了抽象产品类 AbstractProductA 和 AbstractProductB,并实现了 operationA 和 operationB 函数。ConcreteProductA1、ConcreteProductA2、ConcreteProductB1 和 ConcreteProductB2 是抽象工厂模式创建的具体对象。
接下来,定义一个抽象工厂类 AbstractFactory,它声明一组工厂方法 createProductA 和 createProductB,由具体工厂类负责实现这些方法:
class AbstractFactory {
public:virtual ~AbstractFactory() {}virtual AbstractProductA* createProductA() = 0;virtual AbstractProductB* createProductB() = 0;
};
具体工厂类继承这个抽象工厂类,并实现 createProductA 和 createProductB 方法,用于创建具体产品的对象:
class ConcreteFactory1 : public AbstractFactory {
public:AbstractProductA* createProductA() {return new ConcreteProductA1();}AbstractProductB* createProductB() {return new ConcreteProductB1();}
};class ConcreteFactory2 : public AbstractFactory {
public:AbstractProductA* createProductA() {return new ConcreteProductA2();}AbstractProductB* createProductB() {return new ConcreteProductB2();}
};
这两个类继承了抽象工厂类 AbstractFactory,并实现了 createProductA 和 createProductB 方法。ConcreteFactory1 和 ConcreteFactory2 是抽象工厂模式创建的具体工厂。
最后,我们可以在主函数中使用抽象工厂模式创建具体产品的对象:
int main() {// 使用具体工厂1创建产品AbstractFactory* factory1 = new ConcreteFactory1();AbstractProductA* productA1 = factory1->createProductA();AbstractProductB* productB1 = factory1->createProductB();productA1->operationA();productB1->operationB();// 使用具体工厂2创建产品AbstractFactory* factory2 = new ConcreteFactory2();AbstractProductA* productA2 = factory2->createProductA();AbstractProductB* productB2 = factory2->createProductB();productA2->operationA();productB2->operationB();// 释放内存delete productA1;delete productB1;delete factory1;delete productA2;delete productB2;delete factory2;return 0;
}
运行结果如下:
ConcreteProductA1::operationA()
ConcreteProductB1::operationB()
ConcreteProductA2::operationA()
ConcreteProductB2::operationB()
这个示例实现了一个抽象工厂模式,其中抽象工厂类 AbstractFactory 声明了一组工厂方法,具体工厂类 ConcreteFactory1 和 ConcreteFactory2 实现了这些方法,用于创建具体产品的对象。而具体产品类 ConcreteProductA1、ConcreteProductA2、ConcreteProductB1 和 ConcreteProductB2 继承了抽象产品类 AbstractProductA 和 AbstractProductB,并实现了 operationA 和 operationB 函数,表示具体产品的操作。
以上就是用 C++ 实现抽象工厂模式的示例。
抽象工厂模式适用于需要一次性创建一系列相关或相互依赖的对象时,它能够提供一个简单的接口,用于创建这些对象,同时保证这些对象是相互兼容的。由于该模式要求所有具体产品都必须实现相同的接口,因此它提供了更好的灵活性和可扩展性。
相关文章:
《设计模式》工厂模式
《设计模式》工厂模式 工厂模式又分为简单工厂(Simple Factory)、工厂方法(Factory Method)和抽象工厂(Abstract Factory)都是常用的创建型设计模式,它们的主要区别如下: 简单工厂…...
JS - 原型对象、原型链是什么
一 阅读掘金 https://juejin.cn/post/7007416743215759373 https://juejin.cn/post/7007416743215759373 二 阅读掘金小册原型知识点 原型 涉及面试题:如何理解原型?如何理解原型链? 当我们创建一个对象时 let obj { age: 25 }࿰…...
STM32f103 CubeMX封装 led程序
本文代码使用 HAL 库。 文章目录前言一、LED 原理图二、CubeMX创建工程三、LED 相关函数1. 输出电平函数:2. 延时函数:3. 翻转电平函数:四、详细代码实验现象 :总结代码 源码:前言 从这篇文章开始,我们讲解…...
智慧教室系统--温湿度控制系统
随着科技的不断进步,智能化已经成为了各个行业的发展趋势,智慧教室作为未来教育的主流趋势之一,也将受益于这一趋势。而智慧教室中的温湿度控制系统是其中的重要组成部分,为了创造一个舒适、健康、安全的教学环境,智慧…...
只要一直向前定能到达远方,社科院与杜兰大学金融管理硕士项目为你注入动力
在人生这条道路上,我们很远的路要走,不管前方是否平坦,我们只要坚持前向,终将抵达远方。一路上我们付出很多,也收获很多。想要变得更强大,就要不断优化自身,积攒更多的能量,社科院与…...
Java性能-回收算法-Throughout回收算法
垃圾回收算法 理解Throughput回收器 回收器三个基本操作——回收 找到不使用的对象 释放内存 压缩堆碎片 Minor GC和Full GC,每个操作都会标记,释放和压缩对应的目标分代 [63.205s][info][gc,start ] GC(13) Pause Full (Ergonomics) [63.205s][info][…...
立项近7年,索尼产品经理分享PS VR2开发背后的故事
备受期待的索尼PS VR2终于正式发售,VR爱好者们终于有机会体验到《地平线:山之呼唤》等PS VR2独占的VR大作。近期,为了解PS VR2头显诞生背后的故事,外媒AV Watch采访到PS VR2的开发负责人Yasuo Takahashi,在本次采访中&…...
Kubernetes 如何通过ingress-nginx实现应用灰度发布?
在日常的工作中,我们会经常对应用进行发版升级,在互联网公司尤为频繁,主要是为了满足快速的业务发展。我们经常用到的发布方式有滚动更新、蓝绿发布、灰度发布。滚动更新:依次进行新旧替换,直到旧的全部被替换为止。蓝…...
华为OD机试 - 密室逃生游戏(Java) | 机试题+算法思路+考点+代码解析 【2023】
密室逃生游戏 小强增在参加《密室逃生》游戏,当前关卡要求找到符合给定 密码K(升序的不重复小写字母组成) 的箱子, 并给出箱子编号,箱子编号为 1~N 。 每个箱子中都有一个 字符串s ,字符串由大写字母、小写字母、数字、标点符号、空格组成, 需要在这些字符串中找到所有…...
redis的主从复制细节
文章目录复制机制的运作复制的一些事实master持久化关闭时,复制的安全性Redis复制是如何工作的只读性质的slave设置一个slave对master进行验证允许只写入N个附加的副本Redis如何处理过期键重新启动和故障转移后的部分同步复制机制的运作 master和slave的复制运作依…...
SparkSQL
第1章 SparkSQL 概述1.1 SparkSQL 是什么Spark SQL 是 Spark 用于结构化数据(structured data)处理的 Spark 模块。1.2 Hive and SparkSQLSparkSQL 的前身是 Shark,给熟悉 RDBMS 但又不理解 MapReduce 的技术人员提供快速上手的工具。Hive 是早期唯一运行在 Hadoop …...
Python|每日一练|栈|数组|字典树|数组|树|广度优先搜索|单选记录:逆波兰表达式求值|回文对|二叉树的层序遍历
1、逆波兰表达式求值(栈,数组) 根据 逆波兰表示法(https://baike.baidu.com/item/%E9%80%86%E6%B3%A2%E5%85%B0%E5%BC%8F/128437),求表达式的值。 有效的算符包括 、-、*、/ 。每个运算对象可以是整数,也可以是另一个…...
慧教室系统--远程控制系统
随着科技的不断进步,越来越多的教育机构开始使用智慧教室系统来提升教学效果和学生体验。智慧教室系统不仅可以自动化管理设备,还可以实现远程控制,帮助教师和学生更加便捷地使用教室设备。智慧教室系统作为一款领先的智慧教育解决方案&#…...
OSCP-课外1(http万能密码、hydra密码暴力破解http、代码审计、Win缓存区溢出)
目录 难度 主机发现&端口扫描 信息收集 万能密码 hydra密码暴力破解...
ELK日志分析--Logstash
Logstash简介 Logstash安装 测试运行 配置输入和输出 使用Geoip过滤器插件增强数据编辑 配置接收 Beats 的输入 1.Logstash简介 Logstash管道具有两个必需元素input和output,以及一个可选元素filter。输入插件使用来自源的数据,过滤器插件根据你的…...
Mysql插入数据从指定选项中随机选择、插入时间从指定范围随机生成、Navicat使用存储过程模拟插入测试数据
场景 Navicat通过存储过程批量插入mysql数据: Navicat通过存储过程批量插入mysql数据_霸道流氓气质的博客-CSDN博客 上面使用过Navicat借助存储过程批量插入数据。但是插入数据是固定的 insert语句,如果在本地开发时需要模拟插入一些随机数据(从指定…...
【基础算法】关于高精度计算的问题【很高位数数据的加减乘除(相关代码用C++实现)】
文章目录前言1.高精度加法2.高精度减法3.高精度乘法4.高精度除法写在最后前言 当我们在利用计算机进行一些计算时,可能会遇到这类问题 : 有些计算要求精度高,希望计算的数的位数可达几十位甚至几百位,虽然计算机的计算精度也算较…...
事理知识图谱
事理知识图谱能够有力第建模各类事件之间的演化关联关系为事理逻辑推理提供更好的数据基础。 事理图谱定义 事理知识图谱可以将文本中对事件以及事件之间的关系抽取并抽象出来,构建成一个有向图形式的事理知识库。在结构上,事理知识图谱是一个有向有环…...
多綫程之python爬蟲構建
目录多綫程定義簡介原理优点缺点优势代碼框架實現導包打印類爬蟲類構造方法獲取代理設置headers獲取新session獲取源代碼解析網頁解析子頁面保存數據綫程任務得到url啓動多綫程爬蟲總結多綫程 以下定義來自百度百科,看看就好沒仔細寫 定義 多线程(mul…...
【干货】Redis在Java开发中的基本使用和巧妙用法
Redis是一款高性能的内存数据结构存储系统,能够支持多种数据结构类型,如字符串、哈希、列表、集合、有序集合等,也能够支持高级功能,如事务、发布/订阅、Lua脚本等,具有高可用性、高并发性和可扩展性的优点。在Java开发…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
