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

C++实现设计模式---抽象工厂模式 (Abstract Factory)

抽象工厂模式 (Abstract Factory)

抽象工厂模式 是一种创建型设计模式,提供一个接口,用于创建一组相关或互相依赖的对象,而无需指定它们的具体类。


意图

  • 提供一个创建一组相关对象的接口,而无需指定它们的具体类。
  • 解决产品对象之间的相互依赖问题,使得一组对象能协同工作。

使用场景

  1. 需要创建一组相关对象
    • 如 GUI 程序中,窗口、按钮、菜单等需要统一的外观风格。
  2. 需要保证对象之间的兼容性
    • 如游戏开发中,不同种族的士兵和建筑需要互相匹配。
  3. 需要隐藏具体实现
    • 客户端代码只依赖于产品接口,具体实现被封装。

参与者角色

  1. 抽象工厂 (Abstract Factory)
    • 声明一组用于创建相关对象的接口。
  2. 具体工厂 (Concrete Factory)
    • 实现抽象工厂的接口,创建具体的产品。
  3. 抽象产品 (Abstract Product)
    • 定义所有产品的公共接口。
  4. 具体产品 (Concrete Product)
    • 实现抽象产品的接口,为具体工厂生产的对象。

示例代码

以下示例展示了如何使用抽象工厂模式为不同操作系统创建相关的 GUI 组件(按钮和窗口)。

#include <iostream>
#include <memory>// 抽象产品 A: 按钮
class Button {
public:virtual void render() const = 0;virtual ~Button() {}
};// 具体产品 A1: Windows 按钮
class WindowsButton : public Button {
public:void render() const override {std::cout << "Rendering Windows Button" << std::endl;}
};// 具体产品 A2: Mac 按钮
class MacButton : public Button {
public:void render() const override {std::cout << "Rendering Mac Button" << std::endl;}
};// 抽象产品 B: 窗口
class Window {
public:virtual void render() const = 0;virtual ~Window() {}
};// 具体产品 B1: Windows 窗口
class WindowsWindow : public Window {
public:void render() const override {std::cout << "Rendering Windows Window" << std::endl;}
};// 具体产品 B2: Mac 窗口
class MacWindow : public Window {
public:void render() const override {std::cout << "Rendering Mac Window" << std::endl;}
};// 抽象工厂
class GUIFactory {
public:virtual std::unique_ptr<Button> createButton() const = 0;virtual std::unique_ptr<Window> createWindow() const = 0;virtual ~GUIFactory() {}
};// 具体工厂 1: Windows 工厂
class WindowsFactory : public GUIFactory {
public:std::unique_ptr<Button> createButton() const override {return std::make_unique<WindowsButton>();}std::unique_ptr<Window> createWindow() const override {return std::make_unique<WindowsWindow>();}
};// 具体工厂 2: Mac 工厂
class MacFactory : public GUIFactory {
public:std::unique_ptr<Button> createButton() const override {return std::make_unique<MacButton>();}std::unique_ptr<Window> createWindow() const override {return std::make_unique<MacWindow>();}
};// 主函数
int main() {// 选择具体工厂std::unique_ptr<GUIFactory> factory = std::make_unique<WindowsFactory>();// 使用工厂创建产品auto button = factory->createButton();auto window = factory->createWindow();button->render(); // 输出:Rendering Windows Buttonwindow->render(); // 输出:Rendering Windows Window// 切换到另一种具体工厂factory = std::make_unique<MacFactory>();button = factory->createButton();window = factory->createWindow();button->render(); // 输出:Rendering Mac Buttonwindow->render(); // 输出:Rendering Mac Windowreturn 0;
}

代码解析

1. 抽象产品类

定义了产品的公共接口,确保产品类型的一致性:

class Button {
public:virtual void render() const = 0;virtual ~Button() {}
};

2. 具体产品类

实现了抽象产品接口,并提供具体功能:

class WindowsButton : public Button {
public:void render() const override {std::cout << "Rendering Windows Button" << std::endl;}
};

3. 抽象工厂

定义了创建一组相关产品的接口:

class GUIFactory {
public:virtual std::unique_ptr<Button> createButton() const = 0;virtual std::unique_ptr<Window> createWindow() const = 0;virtual ~GUIFactory() {}
};

4. 具体工厂

实现了抽象工厂接口,负责生产具体的产品:

class WindowsFactory : public GUIFactory {
public:std::unique_ptr<Button> createButton() const override {return std::make_unique<WindowsButton>();}std::unique_ptr<Window> createWindow() const override {return std::make_unique<WindowsWindow>();}
};

5. 主函数

客户端代码通过工厂接口创建产品,无需知道具体产品的实现:

std::unique_ptr<GUIFactory> factory = std::make_unique<WindowsFactory>();
auto button = factory->createButton();
auto window = factory->createWindow();
button->render();
window->render();

优缺点

优点

  1. 解耦:客户端代码只依赖抽象工厂和抽象产品,与具体实现无关。
  2. 保证产品一致性:抽象工厂确保一组对象是兼容的。
  3. 扩展性强:可以通过新增具体工厂扩展系统。

缺点

  1. 增加复杂性:每增加一组产品需要新增抽象类和具体类。
  2. 灵活性受限:对现有产品结构的修改可能需要更新所有工厂。

适用场景

  • 跨平台开发:如为不同操作系统设计统一的 GUI。
  • 产品族设计:如游戏中不同种族的士兵和建筑需要互相匹配。
  • 动态扩展产品族:如增加新的平台支持。

改进与扩展

  1. 结合配置文件
    动态选择具体工厂,根据运行时条件决定产品族的创建:

    std::unique_ptr<GUIFactory> factory;
    if (platform == "Windows") {factory = std::make_unique<WindowsFactory>();
    } else {factory = std::make_unique<MacFactory>();
    }
    
  2. 引入依赖注入框架
    通过依赖注入简化工厂选择的逻辑,使得代码更易于维护和测试。


总结

抽象工厂模式通过提供一个接口,用于创建一组相关对象,实现了创建逻辑的集中化和产品族之间的兼容性。
它适用于需要跨平台开发或产品族设计的场景。

相关文章:

C++实现设计模式---抽象工厂模式 (Abstract Factory)

抽象工厂模式 (Abstract Factory) 抽象工厂模式 是一种创建型设计模式&#xff0c;提供一个接口&#xff0c;用于创建一组相关或互相依赖的对象&#xff0c;而无需指定它们的具体类。 意图 提供一个创建一组相关对象的接口&#xff0c;而无需指定它们的具体类。解决产品对象之…...

K8S开启/关闭审计日志

K8S默认禁用审计 开启/关闭 k8s 审计日志 默认 Kubernetes 集群不会输出审计日志信息。通过以下配置&#xff0c;可以开启 Kubernetes 的审计日志功能。 准备审计日志的 Policy 文件配置 API 服务器&#xff0c;开启审计日志重启并验证 准备审计日志 Policy 文件 apiVersio…...

css盒子水平垂直居中

目录 1采用flex弹性布局&#xff1a; 2子绝父相margin&#xff1a;负值&#xff1a; 3.子绝父相margin:auto&#xff1a; 4子绝父相transform&#xff1a; 5通过伪元素 6table布局 7grid弹性布局 文字 水平垂直居中链接&#xff1a;文字水平垂直居中-CSDN博客 以下为盒子…...

px、em 和 rem 的区别:深入理解 CSS 中的单位

文章目录 前言一、px - 像素 (Pixel)二、em - 相对父元素字体大小 (Ems)三、rem - 相对于根元素字体大小 (Root Ems)四、综合比较结语 前言 在CSS中&#xff0c;px、em和rem是三种用于定义尺寸&#xff08;如宽度、高度、边距、填充等&#xff09;的长度单位。它们各自有不同的…...

基于STM32设计的粮食仓库(粮仓)环境监测系统

一、前言 1.1 项目开发背景 随着现代农业的发展和粮食储存规模的扩大&#xff0c;粮仓环境的智能化监控需求日益增长。传统的粮仓管理方式通常依赖人工检测和定期巡查&#xff0c;效率低下且容易出现疏漏&#xff0c;无法及时发现潜在问题&#xff0c;可能导致粮食受潮、霉变…...

【后端面试总结】tls中.crt和.key的关系

tls中.crt和.key的关系 引言 在现代网络通信中&#xff0c;特别是基于SSL/TLS协议的加密通信中&#xff0c;.crt和.key文件扮演着至关重要的角色。这两个文件分别代表了数字证书和私钥&#xff0c;是确保通信双方身份认证和数据传输安全性的基石。本文旨在深入探讨TLS中.crt和…...

日拱一卒(20)——leetcode学习记录:大小为 K 且平均值大于等于阈值的子数组数目

一、题目 给定数组&#xff0c;统计数组中长度为k的子数组且该子数组的平均值大于threshold的数量 二、思路 滑动窗思路&#xff0c;计算长度为k的滑动窗的平均值&#xff0c;关键点在于&#xff0c;每滑动一次&#xff0c;只需要去掉头增加尾&#xff0c;而不需要重新全部计…...

项目练习:若依管理系统字典功能-Vue前端部分

文章目录 一、情景说明二、若依Vue相关代码及配置1、utils代码2、components组件3、api接口代码4、Vuex配置5、main.js配置 三、使用方法1、html部分2、js部分 一、情景说明 我们在做web系统的时候&#xff0c;肯定会遇到一些常量选择场景。 比如&#xff0c;性别&#xff1a;…...

apache-skywalking-apm-10.1.0使用

apache-skywalking-apm-10.1.0使用 本文主要介绍如何使用apache-skywalking-apm-10.1.0&#xff0c;同时配合elasticsearch-8.17.0-windows-x86_64来作为存储 es持久化数据使用。 步骤如下&#xff1a; 一、下载elasticsearch-8.17.0-windows-x86_64 1、下载ES(elasticsear…...

计算机视觉算法实战——视频分析(Video Analysis)

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​​​​ ​​​​​​​​​​​​ ​​​​​ 视频分析是计算机视觉中的一个重要领域&#xff0c;旨在从视频数据中提取有用的信息&…...

全网首发:编译libssh,产生类似undefined reference to `EVP_aes_256_ctr@OPENSSL_1_1_0‘的大量错误

具体错误 前面和后面的&#xff1a; /opt/linux/x86-arm/aarch64-mix210-linux/host_bin/../lib/gcc/aarch64-linux-gnu/7.3.0/../../../../aarch64-linux-gnu/bin/ld: warning: libcrypto.so.1.1, needed by ../lib/libssh.so.4.10.1, not found (try using -rpath or -rpat…...

用python实战excel和word自动化

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 python实现excel和word自动化--批量处理 前言--需求快要期末了需要&#xff0c;提交一个年级的学生成绩数据&#xff0c;也就是几百份。当前我们收集了一份excel表格&#xf…...

【云计算】OpenStack云计算平台

OpenStack云计算平台框架搭建 1.先换源 先换成阿里源: curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo 2.安装框架 yum -y install centos-release-openstack-train 3.安装客户端 yum -y install python-openstackclient 但…...

好用的php商城源码有哪些?

选择一个优秀的商城工具&#xff0c;能更好地帮助大家建立一个好用的商城系统。目前比较流行的都是开源PHP商城系统&#xff0c;那么现实中都有哪些好用的PHP商城源码值得推荐呢&#xff1f;下面就带大家一起来了解一下。 1.TigShop 【推荐指数】&#xff1a;★★★★★☆ 【推…...

docker安装Nginx UI

开源地址&#xff1a;nginx-ui/README-zh_CN.md at dev 0xJacky/nginx-ui GitHub docker run -dit \ --namenginx-ui \ --restartalways \ -e TZAsia/Shanghai \ -v /Users/xiaoping/docker/appdata/nginx:/etc/nginx \ -v /Users/xiaoping/docker/appdata/nginx-ui:/etc/ng…...

为深度学习创建PyTorch张量 - 最佳选项

为深度学习创建PyTorch张量 - 最佳选项 正如我们所看到的&#xff0c;PyTorch张量是torch.Tensor​ PyTorch类的实例。张量的抽象概念与PyTorch张量之间的区别在于&#xff0c;PyTorch张量为我们提供了一个可以在代码中操作的具体实现。 在上一篇文章中&#xff0c;我们看到了…...

详解数据增强中的平移shft操作

Shift 平移是指在数据增强&#xff08;data augmentation&#xff09;过程中&#xff0c;通过对输入图像或目标进行位置偏移&#xff08;平移&#xff09;&#xff0c;让目标在图像中呈现出不同的位置。Shift 平移的目的是增加训练数据的多样性&#xff0c;从而提高模型对目标在…...

CCLINKIE转ModbusTCP网关,助机器人“掀起”工业智能的“惊涛骇浪”

以下是一个稳联技术CCLINKIE转ModbusTCP网关&#xff08;WL-CCL-MTCP&#xff09;连接三菱PLC与机器人的配置案例&#xff1a;设备与软件准备设备&#xff1a;稳联技术WL-CCL-MTCP网关、三菱FX5UPLC、支持ModbusTCP协议的机器人、网线等。 稳联技术ModbusTCP转CCLINKIE网关&…...

类型安全与代码复用的C# 泛型

一、引言&#xff1a;泛型 ——C# 编程的神奇钥匙 在 C# 编程的广袤天地里&#xff0c;泛型宛如一把神奇钥匙&#xff0c;能够开启高效、灵活且安全的代码之门&#x1f6aa;。 想象一下&#xff0c;你是一位经验丰富的建筑师&#xff0c;要建造各种各样的房子&#x1f3e0;。…...

卷积神经05-GAN对抗神经网络

卷积神经05-GAN对抗神经网络 使用Python3.9CUDA11.8Pytorch实现一个CNN优化版的对抗神经网络 简单的GAN图片生成 CNN优化后的图片生成 优化模型代码对比 0-核心逻辑脉络 1&#xff09;Anacanda使用CUDAPytorch2&#xff09;使用本地MNIST进行手写图片训练3&#xff09;…...

vscode使用Marscode编程助手

下载 vscode 在插件里下载Marscode编程助手 插件完成 在这里点击安装&#xff0c;点击后这里出现AI编程插件。...

网络分析仪测试S参数

S参数的测试 一&#xff1a;S参数的定义 S参数&#xff08;Scattering Parameters&#xff0c;散射参数&#xff09;是一个表征器件在射频信号激励下的电气行为的工具&#xff0c;它以输入信号、输出信号为元素的矩阵来表现DUT的“传输”和“散射”效应&#xff0c;输入、输出…...

docker mysql5.7如何设置不区分大小写

环境 docker部署&#xff0c;镜像是5.7&#xff0c;操作系统是centos 操作方式 mysql 配置文件是放在 /etc/mysql/mysql.conf.d/mysqld.cnf&#xff0c; vim /etc/mysql/mysql.conf.d/mysqld.cnf lower_case_table_names1 重启mysql容器 验证 SHOW VARIABLES LIKE low…...

【1】Word:邀请函

目录 题目 文字解析 流程 题目 文字解析 考生文件夹☞Word.docx☞一定要用ms打开&#xff0c;wps打开作答无效☞作答完毕&#xff0c;F12或者手动另存为&#xff08;考生文件夹&#xff1a;路径文件名&#xff09; 注意&#xff1a;一定要检查&#xff0c;很有可能你前面步…...

【gin】中间件使用之jwt身份认证和Cors跨域,go案例

Gin-3 中间件编程及 JWT 身份认证 1. Gin 中间件概述 中间件是处理 HTTP 请求的函数&#xff0c;可以在请求到达路由处理函数之前或之后对请求进行处理。 在 Gin 框架中&#xff0c;中间件常用于处理日志记录、身份验证、权限控制等功能。 router : gin.Default() router.Us…...

【JAVA实战】@FeignClient注解类通用请求封装

背景 最近在编写多个系统数据集成过程中&#xff0c;经常会使用到FeignClient注解标记一个类&#xff0c;类里面编写很多请求方法&#xff0c;如果第三方系统有非常多的URL请求&#xff0c;每个方法对应一个URL请求&#xff0c;那么这个类就会非常的庞大&#xff0c;是否有一种…...

[c语言日寄]精英怪:三子棋(tic-tac-toe)3命慢通[附免费源码]

哈喽盆友们&#xff0c;今天带来《c语言》游戏中[三子棋boss]速通教程&#xff01;我们的目标是一边编写博文&#xff0c;一边快速用c语言实现三子棋游戏。准备好瓜子&#xff0c;我们计时开始&#xff01; 前期规划 在速通中&#xff0c;我们必须要有清晰的前期规划&#xf…...

GORM(Go语言数据交互库)

GORM&#xff08;Go ORM&#xff0c;即对象关系映射&#xff09;是Go语言中非常流行且功能强大的数据库交互库。它简化了与关系型数据库的交互过程&#xff0c;提供了丰富的API来处理各种数据库操作。下面将详细介绍GORM的功能、使用方法和一些高级特性。 1. 安装 首先&#…...

Redis主从同步是怎么实现的?

Redis主从同步是怎么实现的&#xff1f; 主从节点建立连接后&#xff0c;从节点会进行判断&#xff1a; 1.如果这是从节点之前没有同步过数据 属于初次复制&#xff0c;会进行全量重同步&#xff0c;那么从节点会向主节点发送PSYNC?-1 命令&#xff0c;请求主节点进行全量重…...

Flutter中Get.snackbar避免重复显示的实现

在pubspec.yaml中引入依赖框架。 #GetX依赖注解get: ^4.6.5创建一个SnackBarManager管理类去管理每个提示框。 import package:get/get.dart; import package:flutter/material.dart;class SnackBarManager {factory SnackBarManager() > instance;static final SnackBarMa…...