当前位置: 首页 > news >正文

【C++设计模式】(四)创建型模式:简单工厂模式,工厂方法模式,抽象工厂模式

文章目录

  • (四)创建型模式:简单工厂模式,工厂方法模式,抽象工厂模式
    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式

(四)创建型模式:简单工厂模式,工厂方法模式,抽象工厂模式

在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。工厂模式的动机在于通过一个专门的工厂类来封装对象的创建过程,以解耦对象的使用和创建,隐藏复杂的对象实例化逻辑,从而提高代码的灵活性和可维护性。通过工厂模式,客户端代码只需与工厂接口或抽象类交互,而不必直接与具体类耦合,这使得系统更易于扩展和修改。

工厂模式可以分为简单工厂模式,工厂方法模式和抽象工厂模式。

简单工厂模式

简单工厂模式(不属于GoF的23种设计模式):工厂类根据输入的参数决定创建哪一种产品类的实例。

#include <iostream>
#include <string>// 抽象产品类
class Product {
public:virtual void operation() = 0;virtual ~Product() {}  // 虚析构函数,确保正确释放资源
};// 具体产品类 A
class ConcreteProductA : public Product {
public:void operation() override {std::cout << "ConcreteProductA operation." << std::endl;}
};// 具体产品类 B
class ConcreteProductB : public Product {
public:void operation() override {std::cout << "ConcreteProductB operation." << std::endl;}
};// 简单工厂类
class SimpleFactory {
public:// 静态工厂方法,根据传入的字符串类型创建具体的产品对象static Product* createProduct(const std::string& type) {if (type == "A") {return new ConcreteProductA();  // 创建并返回 ConcreteProductA 对象} else if (type == "B") {return new ConcreteProductB();  // 创建并返回 ConcreteProductB 对象} else {return nullptr;        // 如果传入的类型无效,返回空指针}}
};int main() {// 使用简单工厂创建产品 AProduct* productA = SimpleFactory::createProduct("A");if (productA) {productA->operation();delete productA;}// 使用简单工厂创建产品 BProduct* productB = SimpleFactory::createProduct("B");if (productB) {productB->operation();delete productB;}return 0;
}

以上代码通过引入一个工厂类SimpleFactory ,将产品对象AB 的创建过程封装在工厂方法中,从而实现对象创建与使用的分离。客户端只需要通过工厂来获取对象,无需了解对象的创建细节。

工厂方法模式

简单工厂违反了开闭原则(对扩展开放,对修改关闭),因为每当需要引入新产品时,都需要修改工厂类。为了避免这个问题,工厂方法模式定义一个抽象工厂类,通过继承得到可以创建不同产品的工厂。

示例

#include <iostream>
#include <string>// 抽象产品类
class Product {
public:virtual void operation() = 0;virtual ~Product() {}  // 虚析构函数,确保正确释放资源
};// 具体产品类 A
class ConcreteProductA : public Product {
public:void operation() override {std::cout << "ConcreteProductA operation." << std::endl;}
};// 具体产品类 B
class ConcreteProductB : public Product {
public:void operation() override {std::cout << "ConcreteProductB operation." << std::endl;}
};// 抽象工厂类
class Factory {
public:virtual Product* createProduct() = 0;virtual ~Factory() {}  // 虚析构函数,确保正确释放资源
};// 具体工厂类 A,创建 ConcreteProductA
class ConcreteFactoryA : public Factory {
public:Product* createProduct() override {return new ConcreteProductA();}
};// 具体工厂类 B,创建 ConcreteProductB
class ConcreteFactoryB : public Factory {
public:Product* createProduct() override {return new ConcreteProductB();}
};int main() {// 使用具体工厂类 A 创建产品 AFactory* factoryA = new ConcreteFactoryA();Product* productA = factoryA->createProduct();productA->operation();delete productA;delete factoryA;// 使用具体工厂类 B 创建产品 BFactory* factoryB = new ConcreteFactoryB();Product* productB = factoryB->createProduct();productB->operation();delete productB;delete factoryB;return 0;
}

这段代码通过定义一个抽象工厂类Factory来声明创建产品对象的接口,具体的产品创建由具体工厂类(ConcreteFactoryAConcreteFactoryB)来实现。工厂方法模式能在不修改已有代码的情况下,通过增加新的工厂类来创建新的产品类型,实现对开闭原则的遵循。

抽象工厂模式

抽象工厂模式的主要是为了解决在不需要指定具体类的情况下,创建一组相关或依赖对象 (产品族)的需求。它通过提供一个接口来创建一系列相关或依赖对象的工厂,使得客户端可以在不指定具体实现类的情况下,创建产品族中的产品。

#include <iostream>
#include <string>// 抽象产品 A 类
class ProductA {
public:virtual void operation() = 0;virtual ~ProductA() {}  // 虚析构函数,确保正确释放资源
};// 具体产品 A1
class ConcreteProductA1 : public ProductA {
public:void operation() override {std::cout << "ConcreteProductA1 operation." << std::endl;}
};// 具体产品 A2
class ConcreteProductA2 : public ProductA {
public:void operation() override {std::cout << "ConcreteProductA2 operation." << std::endl;}
};// 抽象产品 B 类
class ProductB {
public:virtual void operation() = 0;virtual ~ProductB() {} 
};// 具体产品 B1
class ConcreteProductB1 : public ProductB {
public:void operation() override {std::cout << "ConcreteProductB1 operation." << std::endl;}
};// 具体产品 B2
class ConcreteProductB2 : public ProductB {
public:void operation() override {std::cout << "ConcreteProductB2 operation." << std::endl;}
};// 抽象工厂类
class AbstractFactory {
public:virtual ProductA* createProductA() = 0;virtual ProductB* createProductB() = 0;virtual ~AbstractFactory() {} 
};// 具体工厂 1,创建产品 A1 和 B1
class ConcreteFactory1 : public AbstractFactory {
public:ProductA* createProductA() override {return new ConcreteProductA1();}ProductB* createProductB() override {return new ConcreteProductB1();}
};// 具体工厂 2,创建产品 A2 和 B2
class ConcreteFactory2 : public AbstractFactory {
public:ProductA* createProductA() override {return new ConcreteProductA2();}ProductB* createProductB() override {return new ConcreteProductB2();}
};int main() {// 使用具体工厂 1 创建产品 A1 和 B1AbstractFactory* factory1 = new ConcreteFactory1();ProductA* productA1 = factory1->createProductA();ProductB* productB1 = factory1->createProductB();productA1->operation();productB1->operation();delete productA1;delete productB1;delete factory1;// 使用具体工厂 2 创建产品 A2 和 B2AbstractFactory* factory2 = new ConcreteFactory2();ProductA* productA2 = factory2->createProductA();ProductB* productB2 = factory2->createProductB();productA2->operation();productB2->operation();delete productA2;delete productB2;delete factory2;return 0;
}

相关文章:

【C++设计模式】(四)创建型模式:简单工厂模式,工厂方法模式,抽象工厂模式

文章目录 &#xff08;四&#xff09;创建型模式&#xff1a;简单工厂模式&#xff0c;工厂方法模式&#xff0c;抽象工厂模式简单工厂模式工厂方法模式抽象工厂模式 &#xff08;四&#xff09;创建型模式&#xff1a;简单工厂模式&#xff0c;工厂方法模式&#xff0c;抽象工…...

浅析Golang的Context

文章目录 1. 简介2. 常见用法2.1 控制goroutine的生命周期&#xff08;cancel&#xff09;2.2 传递超时&#xff08;Timeout&#xff09;信息2.3 传递截止时间&#xff08;Deadline&#xff09;2.4 传递请求范围内的全局数据 &#xff08;value&#xff09; 3 特点3.1 上下文的…...

生日礼物C++代码

#include<bits/stdc.h> using namespace std; string s; int a,b; int main(){cout<<" 生日之地"<<\n;cout<<" 1.开始游戏"<<" 2.不想开始"<<\n;cin>>a;if(a1||a2){if(a2)cout<<…...

使用python基于DeepLabv3实现对图片进行语义分割

DeepLabv3 介绍 DeepLabv3 是一种先进的语义分割模型&#xff0c;由 Google Research 团队提出。它在 DeepLab 系列模型的基础上进行了改进&#xff0c;旨在提高图像中像素级分类的准确性。以下是 DeepLabv3 的详细介绍&#xff1a; 概述DeepLabv3 是 DeepLab 系列中的第三代…...

【漏洞复现】泛微OA E-Office do_excel.php 任意文件写入漏洞

》》》产品描述《《《 泛微0-0fice是一款标准化的协同 OA办公软件&#xff0c;泛微协同办公产品系列成员之一,实行通用化产品设计&#xff0c;充分贴合企业管理需求&#xff0c;本着简洁易用、高效智能的原则&#xff0c;为企业快速打造移动化、无纸化、数字化的办公平台。 》》…...

算法(食物链)

240. 食物链 题目 动物王国中有三类动物 A,B,C&#x1d434;,&#x1d435;,&#x1d436;&#xff0c;这三类动物的食物链构成了有趣的环形。 A&#x1d434; 吃 B&#x1d435;&#xff0c;B&#x1d435; 吃 C&#x1d436;&#xff0c;C&#x1d436; 吃 A&#x1d434;。…...

ubuntu20.04系统安装zookeeper简单教程

Ubuntu系统中安装和配置Zookeeper的完整指南 Apache Zookeeper是一个开源的分布式协调服务&#xff0c;广泛用于分布式应用程序中管理配置、提供命名服务、分布式同步以及组服务等。在本教程中&#xff0c;我们将详细介绍如何在Ubuntu系统中安装Zookeeper&#xff0c;并进行相关…...

.NET Core 高性能并发编程

一、高性能大并发架构设计 .NET Core 是一个高性能、可扩展的开发框架&#xff0c;可以用于构建各种类型的应用程序&#xff0c;包括高性能大并发应用程序。为了设计和开发高性能大并发 .NET Core 应用程序&#xff0c;需要考虑以下几个方面&#xff1a; 1. 异步编程 异步编程…...

B 私域模式升级:开源技术助力传统经销体系转型

一、引言 1.1 研究背景 随着市场竞争加剧&#xff0c;传统经销代理体系面临挑战。同时&#xff0c;开源技术发展迅速&#xff0c;为 B 私域升级带来新机遇。在当今数字化时代&#xff0c;企业面临着日益激烈的市场竞争。传统的经销代理体系由于管理效率低下、渠道局限、库存压…...

vue之vuex的使用及举例

Vuex是专门为Vue.js设计的集中式状态管理架构&#xff0c;它允许你将所有的组件共享状态存储在一个单独的地方&#xff0c;即“store”&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。以下是Vuex的基本使用方法&#xff1a; 一、安装Vuex 对于Vue 2项目&…...

使用 vite 快速初始化 shadcn-vue 项目

Vite 1. 创建项目 使用 vite 创建一个新的 vue 项目。 如果你正在使用 JS 模板&#xff0c;需要存在 jsconfig.json 文件才能正确运行 CLI。 # npm 6.x npm create vitelatest my-vue-app --template vue-ts# npm 7, extra double-dash is needed: npm create vitelatest m…...

微信小程序:一个小程序跳转至另一个小程序

一、微信小程序支持一个小程序跳转至另一个小程序吗&#xff1f; 支持。 1.1、目标小程序需开放被跳转&#xff1a;目标小程序需要在其 app.json 文件中配置 navigateToMiniProgramAppIdList&#xff0c;将源小程序的 AppID 加入其中。 1.2、用户授权&#xff1a;用户需要授…...

Java第二阶段---10方法带参---第二节 方法重载(Overloading)

1.概念 在同一个类中&#xff0c;方法名相同&#xff0c;参数列表不同的多个方法构造成方法重载 2.示例 public class Calculator{public int sum(int a,int b){return ab;}public int sum(int a,int b,int c){return abc;} } 3.误区 下面的方法是否属于方法重载&#xff…...

Java Web 之 Session 详解

在 JavaWeb 开发中&#xff0c;Session 就像网站的专属记忆管家&#xff0c;为每个用户保管着重要的信息和状态&#xff0c;确保用户在网站的旅程顺畅无阻。 场景一&#xff1a; 想象你去一家大型超市购物&#xff0c;推着购物车挑选商品。这个购物车就如同 Session&#xff…...

63.5 注意力提示_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录注意力提示生物学中的注意力提示查询、键和值注意力的可视化使用 show_heatmaps 显示注意力权重代码示例 代码解析结果 小结练习 注意力提示 &#x1f3f7;sec_attention-cues 感谢读者对本书的关注&#xff0c;因为读者的注意力是一种稀缺…...

vscode 的terminal 输出打印行数限制设置

修改 VSCODE 的 settings.json文件 "terminal.integrated.scrollback": 100000, {"extensions.ignoreRecommendations": true,"workbench.colorTheme": "Monokai","explorer.confirmDelete": false,"editor.fontSize…...

深入挖掘C++中的特性之一 — 继承

目录 1.继承的概念 2.举个继承的例子 3.继承基类成员访问方式的变化 1.父类成员的访问限定符对在子类中访问父类成员的影响 2.父类成员的访问限定符子类的继承方式对在两个类外访问子类中父类成员的影响 4.继承类模版&#xff08;注意事项&#xff09; 5.父类与子类间的转…...

Linux 下 poll 详解

在Linux系统编程中&#xff0c;poll 是一个强大的多路复用&#xff08;I/O 多路复用&#xff09;函数&#xff0c;用于同时监控多个文件描述符的事件&#xff0c;特别是在处理网络套接字或其他I/O设备时。相比于select&#xff0c;poll 支持监控更多的文件描述符&#xff0c;并…...

virtualbox配置为NAT模式后物理机和虚拟机互通

virtualbox配置为 NAT模式后&#xff0c;虚拟机分配到的 IP地址一般是 10.xx网段的&#xff0c;虚拟机可以通过网络地址转换访问物理机所在的网络&#xff0c;但若不做任何配置&#xff0c;则物理机无法直接访问虚拟机。 virtualbox在提供 NAT配置模式时&#xff0c;也提供了端…...

工程机械车辆挖掘机自卸卡车轮式装载机检测数据集VOC+YOLO格式2644张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2644 标注数量(xml文件个数)&#xff1a;2644 标注数量(txt文件个数)&#xff1a;2644 标注…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...