C++设计模式——抽象工厂模式

文章目录

    • 抽象工厂模式的主要组成部分
    • 抽象工厂模式的一个典型例子
    • 抽象工厂模式用于其他场景
    • 抽象工厂模式与其他设计模式结合使用

C++ 中的抽象工厂模式是一种创建型设计模式,它主要用于处理对象家族的创建,这些对象之间可能存在一定的关联关系或属于相同的产品族。抽象工厂模式的核心目标是提供一个接口,允许客户端通过此接口创建一系列相关或相互依赖的对象,而不必知道具体产生的对象的具体类。

抽象工厂模式的主要组成部分

  1. 抽象工厂(Abstract Factory):这是一个接口,声明了一组用于创建相关或依赖对象的方法,每个方法对应一种产品对象。

    class AbstractFactory {
    public:virtual ~AbstractFactory() {}virtual IProductA* createProductA() = 0; // 创建产品A的抽象方法virtual IProductB* createProductB() = 0; // 创建产品B的抽象方法// ... 可能还有其他产品方法
    };
    
  2. 具体工厂(Concrete Factory):这是抽象工厂接口的具体实现类,它负责创建一个产品族内的具体产品对象。

    class ConcreteFactory1 : public AbstractFactory {
    public:IProductA* createProductA() override { return new ConcreteProductA1(); }IProductB* createProductB() override { return new ConcreteProductB1(); }
    };class ConcreteFactory2 : public AbstractFactory {
    // ...
    };
    
  3. 产品接口(Product Interface):代表产品对象的抽象接口,定义了产品的公共方法。

    class IProductA {
    public:virtual ~IProductA() {}// 声明产品A的相关操作
    };class IProductB {
    public:virtual ~IProductB() {}// 声明产品B的相关操作
    };
    
  4. 具体产品(Concrete Product):实现了产品接口的具体产品类。

    class ConcreteProductA1 : public IProductA {
    // 实现产品A1的具体行为
    };class ConcreteProductB1 : public IProductB {
    // 实现产品B1的具体行为
    };// 同样会有 ConcreteProductA2, ConcreteProductB2 等...
    

使用抽象工厂模式的优势在于:

  • 隔离了具体的产品实现:客户端只需关心抽象工厂的接口,无需了解创建对象的具体细节。
  • 方便产品族的整体替换:如果想切换到同一产品族的不同实现,只需更改使用的具体工厂即可。
  • 确保产品一致性:通过抽象工厂创建的对象遵循一套一致的设计规则,适合那些必须一起工作的对象集合。

然而,抽象工厂模式也有其局限性,例如难以添加新的产品种类,因为它要求修改抽象工厂接口以及相应的具体工厂实现。此外,随着产品数量的增加,系统的复杂性也会提高。

抽象工厂模式的一个典型例子

在实际应用中,抽象工厂模式的一个典型例子是操作系统 GUI 库的创建。比如,我们有一个抽象工厂来创建按钮、文本框等各种 GUI 组件,而每个具体工厂(如 WindowsFactory 或 LinuxFactory)则负责创建相应操作系统下的具体 GUI 组件。

// 抽象工厂接口
class GUIFactory {
public:virtual ~GUIFactory() {}virtual Button* createButton() const = 0;virtual TextBox* createTextBox() const = 0;// 其他组件的创建方法...
};// 具体工厂
class WindowsFactory : public GUIFactory {
public:Button* createButton() const override { return new WindowsButton(); }TextBox* createTextBox() const override { return new WindowsTextBox(); }// ...
};class LinuxFactory : public GUIFactory {
public:Button* createButton() const override { return new LinuxButton(); }TextBox* createTextBox() const override { return new LinuxTextBox(); }// ...
};// 产品接口
class Button {
public:virtual ~Button() {}virtual void draw() const = 0;// ...
};class TextBox {
public:virtual ~TextBox() {}virtual void draw() const = 0;// ...
};// 具体产品
class WindowsButton : public Button {
public:void draw() const override { /*绘制Windows风格的按钮*/ }// ...
};class WindowsTextBox : public TextBox {
public:void draw() const override { /*绘制Windows风格的文本框*/ }// ...
};// Linux下对应的Button和TextBox实现...

在客户端代码中,我们可以根据需要选择合适的工厂来创建一整套风格一致的界面组件:

int main() {GUIFactory* factory;if (isWindowsPlatform()) {factory = new WindowsFactory();} else if (isLinuxPlatform()) {factory = new LinuxFactory();}Button* myButton = factory->createButton();TextBox* myTextBox = factory->createTextBox();// 使用创建出来的组件myButton->draw();myTextBox->draw();delete myButton;delete myTextBox;delete factory;return 0;
}

这样,无论操作系统环境如何变化,客户端代码都可以保持不变,体现了开闭原则——对扩展开放,对修改关闭。同时,由同一家工厂创建出来的组件具有内在的一致性,可以很好地协同工作。

抽象工厂模式用于其他场景

此外,抽象工厂模式还常用于其他场景,例如:

  • 数据库访问:抽象工厂可以定义创建不同数据库连接、执行SQL命令等操作的方法,而具体工厂可以是MySQLFactory、OracleFactory等,分别用来创建各自数据库系统的连接对象和查询命令对象。
// 抽象工厂
class DatabaseFactory {
public:virtual ~DatabaseFactory() {}virtual Connection* createConnection() const = 0;virtual Query* createQuery() const = 0;
};// 具体工厂
class MySQLFactory : public DatabaseFactory {
public:Connection* createConnection() const override { return new MySQLConnection(); }Query* createQuery() const override { return new MySQLQuery(); }
};class OracleFactory : public DatabaseFactory {
public:Connection* createConnection() const override { return new OracleConnection(); }Query* createQuery() const override { return new OracleQuery(); }
};// 产品接口
class Connection {
public:virtual ~Connection() {}virtual bool connect(const std::string& host, int port, const std::string& user, const std::string& password) = 0;// 其他连接相关方法...
};class Query {
public:virtual ~Query() {}virtual ResultSet* execute(const std::string& sql) = 0;// 其他查询相关方法...
};// 具体产品类...

通过这种设计模式,软件架构得以解耦,使得各个部分能够独立变化和发展,同时确保了系统内部组件间的兼容性和一致性。在复杂的应用场景中,抽象工厂模式尤其有助于模块化设计和维护。

抽象工厂模式与其他设计模式结合使用

在更高级别的软件体系结构设计中,抽象工厂模式还可以与其他设计模式结合使用,以构建更为灵活和可扩展的解决方案。例如:

  • 与策略模式结合:抽象工厂可以返回一组实现了某种策略接口的对象,这样客户可以根据需求选择不同的策略组合。例如,在图形渲染引擎中,抽象工厂可以创建不同的渲染策略(如光照策略、纹理策略),然后将它们组合起来形成特定的效果。

  • 与工厂方法模式结合:抽象工厂中的某些方法可以进一步采用工厂方法模式,即在具体工厂内定义创建单个产品的工厂方法,使得产品创建逻辑更加灵活且易于扩展。

  • 与装饰器模式配合:当产品家族中存在需要逐步增强或修改的组件时,可以在获取基础组件后,通过装饰器模式为其添加额外的功能或属性。

  • 与服务定位器模式搭配:在大型系统中,抽象工厂可以与服务定位器模式相结合,通过服务定位器查找并注入所需的抽象工厂实例,以便在运行时决定具体使用哪种工厂。

总的来说,抽象工厂模式是一个强大而实用的设计模式,它不仅帮助我们组织和管理相关联的产品族,而且在很大程度上增强了代码的可复用性和可扩展性。但在实际应用时需要注意权衡其带来的灵活性与增加的复杂性,尤其是在产品家族变动频繁或者产品种类较少的情况下,直接使用简单工厂或工厂方法模式可能更为合适。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

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

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

相关文章

国产航顺HK32F030M: HK32F030MJ4M6_SOP8资料

最小系统 参考资料 [1] 航顺MCU HK32F030MJ4M6-SOP8 各个文件夹简介: Boards:HK32F030xMF4P6开发板的BSP驱动代码。 Documents:HK32F030xMxx数据手册、用户手册、API手册以及HK32F030xMxx开发板原理图。 Package:HK32F030xMxx Ke…

任务系统之API子任务

日常运维工作中有许多的任务要执行,例如项目发布/数据备份/定时巡检/证书更新/漏洞修复等等,大部分的任务都会有多个步骤共同完成,例如一个发布任务会有拉代码、编译、分发、通知等等步骤,而不同的任务可能还包含相同或相似的步骤…

PRL算法调控

伴随汽车电子技术发展,传统轮式车辆制动系统的气体或液体传输管路长,阀类原件多原有的真空助力系统无法兼顾车辆的再生制动功能,而再生制动功能是混合动力车辆是混动车辆最主要的市场优势之一,真空助力器逐渐被eBooster 所取代。针…

微信小程序 - 渲染和逻辑

通信模型 渲染层的界面使用了WebView 进行渲染;逻辑层采用JsCore线程运行JS脚本。 数据驱动 WXML会解析对应model值,并生成js对象,最后生成最终的dom树。 当model发生变更时候,会判断解析wxml后的js对象是否改动,若改动…

[重磅更新] Mac玩游戏必备!Crossover24版现已上线!附免费升级攻略 Crossover软件使用方法安装程序 免费版

好久不见啦,最近一直在忙着研究Mac玩游戏,什么幻兽帕鲁、女神异闻录之类的,有些沉迷了,实在对不住大家… 不过今天还是给大家带来了好消息!那就是让Mac玩游戏不再是笑话的神器,Crossover正式发布了2024版&a…

使用CANoe进行27服务安全认证解密算法

方法:通过cdd文件dll文件进行27服务通过安全认证解密 步骤1:菜单栏选中Diagnostics&XCP这一栏, 步骤2:鼠标左击CANdelaStudio 步骤3:弹出如下弹窗,选择 I accept 步骤4:选择新建 步骤5&…

redis-Redis主从,哨兵和集群模式

一,Redis的主从复制 ​ 主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。这样做的好处是读写分离,性能扩展,容灾快速恢复。 1.1 环境搭建 如果你的redi…

ModStartCMS v8.1.0 图片前端压缩,抖音授权登录

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用,支持后台一键快速安装,让开发者能快的实现业务功能开发。 系统完全开源,基于 Apache 2.0 开源协议,免费且不限制商业使用。 功能特性 丰富的模块市…

手机AI摄影时代开启,传音引领行业标准化建设

今年春节,AI摄影可谓大出风头。人们在社交平台晒出自己在龙年的AI写真,极大地增添了节日的氛围感,也让我们看到了“AI摄影”的价值。新年伊始,手机巨头们纷纷布局该赛道,基于AI大模型实现的影像功能成为业界关注焦点。…

Java Web(十)--jQuery

介绍 官网文档:jQuery 教程 jQuery API 中文文档 | jQuery API 中文在线手册 | jquery api 下载 | jquery api chm 下载地址:https://jquery.com/download/%20jQuery jQuery 是一个快速的,简洁的 javaScrip工具库,使用户能更方…

C语言 变量

变量其实只不过是程序可操作的存储区的名称。C 中每个变量都有特定的类型,类型决定了变量存储的大小和布局,该范围内的值都可以存储在内存中,运算符可应用于变量上。 变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头…

全网最新的软件测试面试八股文

🍅 视频学习:文末有免费的配套视频可观看 🍅 关注公众号【互联网杂货铺】,回复 1 ,免费获取软件测试全套资料,资料在手,涨薪更快 测试技术面试题 1、什么是兼容性测试?兼容性测试侧…

一、前端开发

#视频链接:https://www.bilibili.com/video/BV1rT4y1v7uQ?p1&vd_source1717654b9cbbc6a773c2092070686a95 前端开发 前端开发1、快速开发网站2、浏览器能识别的标签2.1 编码(head)2.2 title(head)2.3 标题2.4 div和span练习题2.5 超链接…

03|索引优化

数据准备 创建联合索引 KEY idx_name_age_position (name,age,position) USING BTREE CREATE TABLE employees (id int(11) NOT NULL AUTO_INCREMENT,name varchar(24) NOT NULL DEFAULT COMMENT 姓名,age int(11) NOT NULL DEFAULT 0 COMMENT 年龄,position varchar(20) NO…

内存操作函数(c语言)

目录 概述1. memcpy函数2.memcpy函数的模拟实现3. memcmp函数4.memcmp函数的模拟实现5. memset函数6.memset函数的模拟实现7. memmove函数8.memmove函数的模拟实现结语 概述 C语言提供了一些非常有用的内存操作函数,其中包括memcpy、memcmp、memset和memmove。这些…

MQTT简介

https://mqtt.org/ MQTT(Message Queuing Telemetry Transport) 一种轻量级的,基于发布订阅模式的通信协议,用于在物联网和机器与机器(M2M)通信中传输消息。 它具有低带宽和低功耗的特点,适用于…

vue3 开发记录

1.引入nprogress插件,显示未声明文件 无法找到模块“nprogress”的声明文件。 解决方法: vite-env.d.ts // 解决引入模块的报错提示 declare module "nprogress";2.在 .evn 文件中创建了自定义环境变量 VITE_APP_BASE_URL 但在项目中使用时出…

【学习记录】Resnet

Resnet的残差块 BasicBlock模块: Resnet的作用 解决梯度消失。网络越深,会导致梯度消失。Resnet可以解决梯度消失的问题。 Resnet的原理 参考视频:https://www.bilibili.com/video/BV1cM4y117ob/?spm_id_from333.337.search-card.all.cl…

请查收:2024年腾讯云服务器优惠价格表_租用配置报价

一张表看懂腾讯云服务器租用优惠价格表,一目了然,腾讯云服务器分为轻量应用服务器和云服务器CVM,CPU内存配置从2核2G、2核4G、4核8G、8核16G、4核16G、8核32G、16核32G、16核64等配置可选,公网带宽1M、3M、5M、12M、18M、22M、28M…

FreeRTOS任务切换

目录 一、PendSV异常 二、任务切换场合 1、执行系统调用 2、滴答定时器(SysTick)中断 三、PendSV中断服务函数 1、分析xPortPendSVHandler中断服务函数 四、查找下一个要运行的任务的两种方法 1、获取下一个要运行的任务 2、查找下一个要运行的任务的两种方法 2.1、通…