【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 ,将产品对象A和B 的创建过程封装在工厂方法中,从而实现对象创建与使用的分离。客户端只需要通过工厂来获取对象,无需了解对象的创建细节。
工厂方法模式
简单工厂违反了开闭原则(对扩展开放,对修改关闭),因为每当需要引入新产品时,都需要修改工厂类。为了避免这个问题,工厂方法模式定义一个抽象工厂类,通过继承得到可以创建不同产品的工厂。
示例
#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来声明创建产品对象的接口,具体的产品创建由具体工厂类(ConcreteFactoryA 和 ConcreteFactoryB)来实现。工厂方法模式能在不修改已有代码的情况下,通过增加新的工厂类来创建新的产品类型,实现对开闭原则的遵循。
抽象工厂模式
抽象工厂模式的主要是为了解决在不需要指定具体类的情况下,创建一组相关或依赖对象 (产品族)的需求。它通过提供一个接口来创建一系列相关或依赖对象的工厂,使得客户端可以在不指定具体实现类的情况下,创建产品族中的产品。
#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++设计模式】(四)创建型模式:简单工厂模式,工厂方法模式,抽象工厂模式
文章目录 (四)创建型模式:简单工厂模式,工厂方法模式,抽象工厂模式简单工厂模式工厂方法模式抽象工厂模式 (四)创建型模式:简单工厂模式,工厂方法模式,抽象工…...
浅析Golang的Context
文章目录 1. 简介2. 常见用法2.1 控制goroutine的生命周期(cancel)2.2 传递超时(Timeout)信息2.3 传递截止时间(Deadline)2.4 传递请求范围内的全局数据 (value) 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 是一种先进的语义分割模型,由 Google Research 团队提出。它在 DeepLab 系列模型的基础上进行了改进,旨在提高图像中像素级分类的准确性。以下是 DeepLabv3 的详细介绍: 概述DeepLabv3 是 DeepLab 系列中的第三代…...
【漏洞复现】泛微OA E-Office do_excel.php 任意文件写入漏洞
》》》产品描述《《《 泛微0-0fice是一款标准化的协同 OA办公软件,泛微协同办公产品系列成员之一,实行通用化产品设计,充分贴合企业管理需求,本着简洁易用、高效智能的原则,为企业快速打造移动化、无纸化、数字化的办公平台。 》》…...
算法(食物链)
240. 食物链 题目 动物王国中有三类动物 A,B,C𝐴,𝐵,𝐶,这三类动物的食物链构成了有趣的环形。 A𝐴 吃 B𝐵,B𝐵 吃 C𝐶,C𝐶 吃 A𝐴。…...
ubuntu20.04系统安装zookeeper简单教程
Ubuntu系统中安装和配置Zookeeper的完整指南 Apache Zookeeper是一个开源的分布式协调服务,广泛用于分布式应用程序中管理配置、提供命名服务、分布式同步以及组服务等。在本教程中,我们将详细介绍如何在Ubuntu系统中安装Zookeeper,并进行相关…...
.NET Core 高性能并发编程
一、高性能大并发架构设计 .NET Core 是一个高性能、可扩展的开发框架,可以用于构建各种类型的应用程序,包括高性能大并发应用程序。为了设计和开发高性能大并发 .NET Core 应用程序,需要考虑以下几个方面: 1. 异步编程 异步编程…...
B 私域模式升级:开源技术助力传统经销体系转型
一、引言 1.1 研究背景 随着市场竞争加剧,传统经销代理体系面临挑战。同时,开源技术发展迅速,为 B 私域升级带来新机遇。在当今数字化时代,企业面临着日益激烈的市场竞争。传统的经销代理体系由于管理效率低下、渠道局限、库存压…...
vue之vuex的使用及举例
Vuex是专门为Vue.js设计的集中式状态管理架构,它允许你将所有的组件共享状态存储在一个单独的地方,即“store”,并以相应的规则保证状态以一种可预测的方式发生变化。以下是Vuex的基本使用方法: 一、安装Vuex 对于Vue 2项目&…...
使用 vite 快速初始化 shadcn-vue 项目
Vite 1. 创建项目 使用 vite 创建一个新的 vue 项目。 如果你正在使用 JS 模板,需要存在 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…...
微信小程序:一个小程序跳转至另一个小程序
一、微信小程序支持一个小程序跳转至另一个小程序吗? 支持。 1.1、目标小程序需开放被跳转:目标小程序需要在其 app.json 文件中配置 navigateToMiniProgramAppIdList,将源小程序的 AppID 加入其中。 1.2、用户授权:用户需要授…...
Java第二阶段---10方法带参---第二节 方法重载(Overloading)
1.概念 在同一个类中,方法名相同,参数列表不同的多个方法构造成方法重载 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.误区 下面的方法是否属于方法重载ÿ…...
Java Web 之 Session 详解
在 JavaWeb 开发中,Session 就像网站的专属记忆管家,为每个用户保管着重要的信息和状态,确保用户在网站的旅程顺畅无阻。 场景一: 想象你去一家大型超市购物,推着购物车挑选商品。这个购物车就如同 Sessionÿ…...
63.5 注意力提示_by《李沐:动手学深度学习v2》pytorch版
系列文章目录 文章目录 系列文章目录注意力提示生物学中的注意力提示查询、键和值注意力的可视化使用 show_heatmaps 显示注意力权重代码示例 代码解析结果 小结练习 注意力提示 🏷sec_attention-cues 感谢读者对本书的关注,因为读者的注意力是一种稀缺…...
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.继承类模版(注意事项) 5.父类与子类间的转…...
Linux 下 poll 详解
在Linux系统编程中,poll 是一个强大的多路复用(I/O 多路复用)函数,用于同时监控多个文件描述符的事件,特别是在处理网络套接字或其他I/O设备时。相比于select,poll 支持监控更多的文件描述符,并…...
virtualbox配置为NAT模式后物理机和虚拟机互通
virtualbox配置为 NAT模式后,虚拟机分配到的 IP地址一般是 10.xx网段的,虚拟机可以通过网络地址转换访问物理机所在的网络,但若不做任何配置,则物理机无法直接访问虚拟机。 virtualbox在提供 NAT配置模式时,也提供了端…...
工程机械车辆挖掘机自卸卡车轮式装载机检测数据集VOC+YOLO格式2644张3类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2644 标注数量(xml文件个数):2644 标注数量(txt文件个数):2644 标注…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
