【第二节】C++设计模式(创建型模式)-抽象工厂模式

news2025/5/11 13:44:22

目录

引言

一、抽象工厂模式概述

二、抽象工厂模式的应用

三、抽象工厂模式的适用场景

四、抽象工厂模式的优缺点

五、总结


 

引言

        抽象工厂设计模式是一种创建型设计模式,旨在解决一系列相互依赖对象的创建问题。它与工厂方法模式密切相关,但在应用场景和实现方式上有显著区别。本文将通过理论讲解和代码示例,深入探讨抽象工厂模式的核心思想、适用场景及其优缺点。

一、抽象工厂模式概述

(1) 核心思想

        抽象工厂模式通过定义一个创建一系列相关或相互依赖对象的接口,将具体对象的创建工作封装到具体的工厂类中。它强调面向接口编程,支持多种变化需求,同时确保生成的对象的关联性和兼容性。

(2)与工厂方法模式的关系

工厂方法模式:解决单一对象的创建问题,通过子类化实现对象的创建。
抽象工厂模式:解决一系列相互依赖对象的创建问题,通过一个工厂类创建多个相关对象。

(3)主要解决的问题

        避免直接使用 `new` 操作符导致的对象绑定问题。
        支持多种变化需求(如多种数据库、多种产品系列)。
        确保生成的对象的关联性和兼容性。

(4)数据库访问层示例

需求分析
        在数据库访问层中,通常需要创建以下对象:
        数据库连接(`IDbConnection`)
        命令对象(`IDbCommand`)
        数据读取器对象(`IDataReader`)

        不同数据库(如 MySQL、SQL Server)需要不同的实现类。如果直接使用 `new` 关键字创建对象,会导致代码与具体数据库绑定,难以支持多种数据库。

面向接口编程
        通过定义接口 `IDbConnection`、`IDbCommand` 和 `IDataReader`,实现面向接口编程。具体数据库的连接、命令和读取器类继承自这些接口,从而支持多种数据库的实现。

工厂方法模式的局限性
        工厂方法模式可以解决单一对象的创建问题,但不适用于创建多个相互依赖的对象。例如,不同工厂可能创建不兼容的对象组合,导致错误。

二、抽象工厂模式的应用

(1)解决对象组合问题

        抽象工厂模式将多个相互依赖对象的创建工作合并到一个工厂类中。通过一个工厂类创建所有相关对象,确保对象之间的兼容性。

(2)代码示例

        以下是一个简单的抽象工厂模式实现示例,展示了如何创建一组相关对象。

        Abstract Factory模式的核心价值在于通过抽象工厂接口将一组相关或依赖对象的创建过程统一封装到具体工厂类(ConcreteFactory)中。这种集中化的对象创建机制不仅符合单一职责原则,更重要的是通过消除分散的创建逻辑,显著降低了系统在对象实例化层面的维护复杂度,为产品族的扩展提供了规范的框架基础。 


产品类定义

// Product.h
#ifndef _PRODUCT_H_
#define _PRODUCT_H_

class AbstractProductA {
public:
    virtual ~AbstractProductA();
protected:
    AbstractProductA();
};

class AbstractProductB {
public:
    virtual ~AbstractProductB();
protected:
    AbstractProductB();
};

class ProductA1 : public AbstractProductA {
public:
    ProductA1();
    ~ProductA1();
};

class ProductA2 : public AbstractProductA {
public:
    ProductA2();
    ~ProductA2();
};

class ProductB1 : public AbstractProductB {
public:
    ProductB1();
    ~ProductB1();
};

class ProductB2 : public AbstractProductB {
public:
    ProductB2();
    ~ProductB2();
};

#endif // ~_PRODUCT_H_

工厂类定义

// AbstractFactory.h
#ifndef _ABSTRACTFACTORY_H_
#define _ABSTRACTFACTORY_H_

class AbstractProductA;
class AbstractProductB;

class AbstractFactory {
public:
    virtual ~AbstractFactory();
    virtual AbstractProductA* CreateProductA() = 0;
    virtual AbstractProductB* CreateProductB() = 0;
protected:
    AbstractFactory();
};

class ConcreteFactory1 : public AbstractFactory {
public:
    ConcreteFactory1();
    ~ConcreteFactory1();
    AbstractProductA* CreateProductA();
    AbstractProductB* CreateProductB();
};

class ConcreteFactory2 : public AbstractFactory {
public:
    ConcreteFactory2();
    ~ConcreteFactory2();
    AbstractProductA* CreateProductA();
    AbstractProductB* CreateProductB();
};

#endif // ~_ABSTRACTFACTORY_H_

工厂类实现

// AbstractFactory.cpp
#include "AbstractFactory.h"
#include "Product.h"
#include <iostream>
using namespace std;

AbstractFactory::AbstractFactory() {}
AbstractFactory::~AbstractFactory() {}

ConcreteFactory1::ConcreteFactory1() {}
ConcreteFactory1::~ConcreteFactory1() {}
AbstractProductA* ConcreteFactory1::CreateProductA() {
    return new ProductA1();
}
AbstractProductB* ConcreteFactory1::CreateProductB() {
    return new ProductB1();
}

ConcreteFactory2::ConcreteFactory2() {}
ConcreteFactory2::~ConcreteFactory2() {}
AbstractProductA* ConcreteFactory2::CreateProductA() {
    return new ProductA2();
}
AbstractProductB* ConcreteFactory2::CreateProductB() {
    return new ProductB2();
}

测试程序

// main.cpp
#include "AbstractFactory.h"
#include <iostream>
using namespace std;

int main(int argc, char* argv[]) {
    AbstractFactory* cf1 = new ConcreteFactory1();
    cf1->CreateProductA();
    cf1->CreateProductB();

    AbstractFactory* cf2 = new ConcreteFactory2();
    cf2->CreateProductA();
    cf2->CreateProductB();

    return 0;
}

        从实现层面来看,Abstract Factory模式通过具体工厂类(ConcreteFactory1)对产品对象的创建过程进行封装。在测试用例中可见,当需要构建一组相关联的产品对象(如ProductA1、ProductA2)时,客户端仅需依赖统一的工厂接口进行操作,而无需关注具体产品的实例化细节。这种设计不仅降低了代码的耦合度,更重要的是将原本分散在各处的对象创建逻辑集中管理,显著提升了系统的可维护性和扩展性。

        在理解设计模式的过程中,区分Abstract Factory模式与Factory模式的概念差异是一个关键的学习点。本质上,Abstract Factory模式旨在为一系列具有关联性或依赖关系的对象族提供统一的创建接口,它关注的是产品家族的创建逻辑;而Factory模式则专注于单一类型对象的实例化过程,通过将对象的创建延迟到子类来实现扩展性,其核心是单一产品的创建机制。从实现角度来看,Abstract Factory模式通常以Factory模式为基础,通过具体工厂类(ConcreteFactory1)来实现对多个关联产品的协同创建,这种层次化的设计体现了模式间的组合应用。

三、抽象工厂模式的适用场景

(1)一系列相互依赖对象的创建
        抽象工厂模式适用于需要创建一组相关对象的场景,例如:
                数据库访问层中的连接、命令和读取器对象。
                游戏开发中的不同等级怪物及其相关对象。

(2)支持多系列对象的需求变化
        当需求变化时,抽象工厂模式可以轻松支持更多系列对象的创建工作,而无需修改现有代码。

四、抽象工厂模式的优缺点

优点
        高内聚性:将相关对象的创建集中在一个工厂类中,提高代码的内聚性。
        易于扩展:支持新增系列对象的创建,符合开闭原则。
        降低耦合:通过面向接口编程,降低客户端与具体实现类的耦合。

缺点
        难以应对新对象的需求变动:如果需要新增对象类型,可能需要修改抽象工厂接口及其所有实现类。
        复杂性增加:随着系列对象的增多,工厂类的数量也会增加,导致系统复杂性上升。

五、总结

        抽象工厂模式是一种强大的设计模式,适用于解决一系列相互依赖对象的创建问题。它通过面向接口编程和封装对象创建逻辑,提高了代码的灵活性和可维护性。然而,在面对新对象需求变动时,抽象工厂模式可能显得不够灵活。因此,在实际开发中,应根据具体需求选择合适的设计模式。

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

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

相关文章

【开关电源】汽车前端电源保护电路设计

前言&#xff1a; 汽车电池端子在启动或者保养过程中被反接&#xff0c;如果对这些故障不能及时处理&#xff0c;就可能导致ECU或供电设备被损坏&#xff1b;此外在供电过程中电压也存在不稳定的情况。在EMC测试中ISO16750和ISO7637也会有负电压的情况。 肖特基二极管和 P 沟道…

网络运维学习笔记 017 HCIA-Datacom综合实验01

文章目录 综合实验1实验需求总部特性 分支8分支9 配置一、 基本配置&#xff08;IP二层VLAN链路聚合&#xff09;ACC_SWSW-S1SW-S2SW-Ser1SW-CoreSW8SW9DHCPISPGW 二、 单臂路由GW 三、 vlanifSW8SW9 四、 OSPFSW8SW9GW 五、 DHCPDHCPGW 六、 NAT缺省路由GW 七、 HTTPGW 综合实…

C++单例模板类,继承及使用

前言&#xff1a; 单例模式可以参考如下文章&#xff1a; 我的设计模式&#xff0c;单例模式的设计和实现 c 单例模式的模板类 - 川野散人 - 博客园 1.为什么需要单例模板类&#xff1f; 场景问题&#xff1a; 如果需要100个单例类就需要设计100个单例模式&#xff0c;代…

nodejs:vue 3 + vite 作为前端,将 html 填入<iframe>,在线查询英汉词典

向 doubao.com/chat/ 提问&#xff1a; node.js js-mdict 作为后端&#xff0c;vue 3 vite 作为前端&#xff0c;编写在线查询英汉词典 后端部分&#xff08;express js-mdict &#xff09; 详见上一篇&#xff1a;nodejs&#xff1a;express js-mdict 作为后端&#xff…

现场可以通过手机或者pad实时拍照上传到大屏幕的照片墙现场大屏电子照片墙功能

现场可以通过手机或者pad实时拍照上传到大屏幕的照片墙现场大屏电子照片墙功能&#xff0c;每个人都可以通过手机实时拍照上传到大屏幕上,同时还可以发布留言内容&#xff0c;屏幕上会同步滚动播放展示所有人的照片和留言。相比校传统的照片直播功能更加灵活方便&#xff0c;而…

《FFTformer:基于频域的高效Transformer用于高质量图像去模糊》

paper&#xff1a;2211.12250 GitHub&#xff1a;kkkls/FFTformer: [CVPR 2023] Effcient Frequence Domain-based Transformer for High-Quality Image Deblurring CVPR 2023 目录 摘要 1、介绍 2、相关工作 2.1 基于深度CNN的图像去模糊方法 2.2 Transformer及其在图…

ChātGPT赋能的“SolidWorks工具箱”:重塑3D设计效率新标杆

ChātGPT精心打造的“SolidWorks工具箱”正逐步成为3D设计领域中的一颗璀璨新星&#xff0c;其集高效、便捷与创新于一身&#xff0c;为用户带来了前所未有的设计体验。以下是对这一革命性工具箱的深度剖析与美化呈现&#xff1a; 一、核心功能&#xff1a;重塑设计流程&#x…

基于CNN的FashionMNIST数据集识别3——模型验证

源码 import torch import torch.utils.data as Data from torchvision import transforms from torchvision.datasets import FashionMNIST from model import LeNetdef test_data_process():test_data FashionMNIST(root./data,trainFalse,transformtransforms.Compose([tr…

洛谷P1135多题解

解法1&#xff1a;BFS&#xff0c;有n个节点每个节点最多被访问一次&#xff0c;所以BFS时间复杂度为O(n)。注意ab的特判。 #include<iostream> #include<cstring> #include<queue> using namespace std; const int N 205; int n, a, b; int k[N], s[N]; b…

用AI写游戏3——deepseek实现kotlin android studio greedy snake game 贪吃蛇游戏

项目下载 https://download.csdn.net/download/AnalogElectronic/90421306 项目结构 就是通过android studio 建空项目&#xff0c;改下MainActivity.kt的内容就完事了 ctrlshiftalts 看项目结构如下 核心代码 MainActivity.kt package com.example.snakegame1// MainA…

论文解读 | AAAI'25 Cobra:多模态扩展的大型语言模型,以实现高效推理

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 点击 阅读原文 观看作者讲解回放&#xff01; 个人信息 作者&#xff1a;赵晗&#xff0c;浙江大学-西湖大学联合培养博士生 内容简介 近年来&#xff0c;在各个领域应用多模态大语言模型&#xff08;MLLMs&…

DPVS-3: 双臂负载均衡测试

测试拓扑 双臂模式&#xff0c; 使用两个网卡&#xff0c;一个对外&#xff0c;一个对内。 Client host是物理机&#xff0c; RS host都是虚拟机。 LB host是物理机&#xff0c;两个CX5网卡分别在两个子网。 配置文件 用dpvs.conf.sample作为双臂配置文件&#xff0c;其中…

记一次复杂分页查询的优化历程:从临时表到普通表的架构演进

1. 问题背景 在项目开发中&#xff0c;我们需要实现一个复杂的分页查询功能&#xff0c;涉及大量 IP 地址数据的处理和多表关联。在我接手这个项目的时候,代码是这样的 要知道代码里面的 ipsList 数据可能几万条甚至更多,这样拼接的sql,必然是要内存溢出的,一味地扩大jvm参数不…

架构师面试(六):熔断和降级

问题 在千万日活的电商系统中&#xff0c;商品列表页服务通过 RPC 调用广告服务&#xff1b;经过统计发现&#xff0c;在最近10秒的时间里&#xff0c;商品列表页服务在对广告服务的调用中有 98% 的调用是超时的&#xff1b; 针对这个场景&#xff0c;下面哪几项的说法是正确的…

细说 Java 引用(强、软、弱、虚)和 GC 流程(二)

一、前文回顾 在 细说Java 引用&#xff08;强、软、弱、虚&#xff09;和 GC 流程&#xff08;一&#xff09; 我们对Java 引用有了总体的认识&#xff0c;本文将继续深入分析 Java 引用在 GC 时的一些细节。 还是从我们在前文中提到的引用流程图里说起&#xff0c;这里不清…

【深度学习】Unet的基础介绍

U-Net是一种用于图像分割的深度学习模型&#xff0c;特别适合医学影像和其他需要分割细节的任务。如图&#xff1a; Unet论文原文 为什么叫U-Net&#xff1f; U-Net的结构像字母“U”&#xff0c;所以得名。它的结构由两个主要部分组成&#xff1a; 下采样&#xff08;编码…

ROS2机器人开发--服务通信与参数通信

服务通信与参数通信 在 ROS 2 中&#xff0c;服务&#xff08;Services&#xff09;通信和参数&#xff08;Parameters&#xff09;通信是两种重要的通信机制。服务是基于请求和响应的双向通信机制。参数用于管理节点的设置&#xff0c;并且参数通信是基于服务通信实现的。 1 …

DeepSeek写贪吃蛇手机小游戏

DeepSeek写贪吃蛇手机小游戏 提问 根据提的要求&#xff0c;让DeepSeek整理的需求&#xff0c;进行提问&#xff0c;内容如下&#xff1a; 请生成一个包含以下功能的可运行移动端贪吃蛇H5文件&#xff1a; 要求 蛇和食物红点要清晰&#xff0c;不超过屏幕外 下方有暂停和重新…

Python安全之反序列化——pickle/cPickle

一&#xff0e; 概述 Python中有两个模块可以实现对象的序列化&#xff0c;pickle和cPickle&#xff0c;区别在于cPickle是用C语言实现的&#xff0c;pickle是用纯python语言实现的&#xff0c;用法类似&#xff0c;cPickle的读写效率高一些。使用时一般先尝试导入cPickle&…

Deepin(Linux)安装MySQL指南

1.下载 地址&#xff1a;https://downloads.mysql.com/archives/community/ 2.将文件解压到 /usr/local 目录下 先cd到安装文件所在目录再解压&#xff0c;本机是cd /home/lu01/Downloads sudo tar -xvJf mysql-9.2.0-linux-glibc2.28-x86_64.tar.xz -C /usr/local3.创建软链…