C++设计模式——Abstract Factory Pattern抽象工厂模式

devtools/2024/11/30 1:30:16/

一、抽象工厂模式的定义

抽象工厂模式是一种创建型设计模式,它提供了一种将相关/依赖对象组合在一起创建的方式,而无需指定它们的具体类。

抽象工厂模式与工厂方法模式的区别:

工厂方法模式将对象的创建过程延迟到子类中,允许用户通过一个统一的接口来请求他们想要的具体产品,而无需知道产品的具体实现。在这个模式中,工厂类只负责生产同一系列的产品,但具体哪种产品由子类决定。

抽象工厂模式更进一步,它提供了一个接口,用于创建一系列相关的或相互依赖的对象,而不是单一对象。抽象工厂封装了产品系列的创建逻辑,客户端不需要知道如何创建具体的产品对象,只需要关心最终能得到哪些产品。这种模式通常用于解决产品集的变化而无需修改客户端代码的情况。

当需要面对多个产品等级结构时,更推荐使用抽象工厂模式

抽象工厂模式在现实生活中的抽象实例:

汽车制造:对于每个品牌的汽车,公司都有不同的组件供应商,例如发动机、座椅和轮胎供应商。在抽象工厂模式中,汽车制造公司充当工厂角色,而不同品牌的汽车和不同的组件供应商充当具体产品。

美食餐厅:餐厅可以提供多种类型的饮料和食物,比如咖啡和披萨。每种类型的饮料和食物都有不同的原料供应商。在抽象工厂模式中,餐厅充当工厂角色,而不同类型的饮料和食物以及不同的原料供应商充当具体产品。

电子产品制造:假设有一家电子产品制造公司,对于每种电子产品,公司都有不同的组件供应商,例如显示屏、处理器和电池供应商。在抽象工厂模式中,电子产品制造公司充当工厂角色,而不同类型的电子产品和不同的组件供应商充当具体产品。

二、抽象工厂模式的结构

抽象工厂模式主要包含以下组件:

1.抽象工厂(AbstractFactory):它声明了创建一系列具有相同接口的对象的方法,这些对象代表不同的产品。

2.具体工厂(ConcreteFactory):是抽象工厂的具体实现,负责创建具体产品对象。每个具体工厂对应了一系列的具体产品。

3.抽象产品(AbstractProduct):它声明了产品对象的接口,包含了创建产品的公共方法。

4.具体产品(ConcreteProduct):是抽象产品的具体实现。

组件之间的工作步骤如下:

1.定义一个抽象工厂类, 这个类声明了一系列产品的创建方法,但不提供方法的具体代码实现。

2.代码在特定的上下文环境中调用具体工厂对象来负责创建一系列的产品。

3. 当客户端需要一个产品时,它向抽象工厂发送请求。抽象工厂根据当前需求选择合适的具体工厂,并由该工厂返回所需的产品实例。

抽象工厂模式将具体产品的创建和使用进行了解耦,使得客户端与具体产品的实现分离,能够很方便地替换不同的产品系列。

对应UML类图:

三、抽象工厂模式代码样例

#include <iostream>
using namespace std;
// Abstract Product A
class AbstractProductA {
public:virtual void operationA() = 0;
};
// Concrete Product A1
class ProductA1 : public AbstractProductA {
public:void operationA() override {cout << "Product A1 operation" << endl;}
};
// Concrete Product A2
class ProductA2 : public AbstractProductA {
public:void operationA() override {cout << "Product A2 operation" << endl;}
};
// Abstract Product B
class AbstractProductB {
public:virtual void operationB() = 0;
};
// Concrete Product B1
class ProductB1 : public AbstractProductB {
public:void operationB() override {cout << "Product B1 operation" << endl;}
};
// Concrete Product B2
class ProductB2 : public AbstractProductB {
public:void operationB() override {cout << "Product B2 operation" << endl;}
};
// Abstract Factory
class AbstractFactory {
public:virtual AbstractProductA* createProductA() = 0;virtual AbstractProductB* createProductB() = 0;
};
// Concrete Factory 1
class ConcreteFactory1 : public AbstractFactory {
public:AbstractProductA* createProductA() override {return new ProductA1();}AbstractProductB* createProductB() override {return new ProductB1();}
};
// Concrete Factory 2
class ConcreteFactory2 : public AbstractFactory {
public:AbstractProductA* createProductA() override {return new ProductA2();}AbstractProductB* createProductB() override {return new ProductB2();}
};
int main() {AbstractFactory* factory1 = new ConcreteFactory1();AbstractProductA* productA1 = factory1->createProductA();AbstractProductB* productB1 = factory1->createProductB();productA1->operationA();productB1->operationB();AbstractFactory* factory2 = new ConcreteFactory2();AbstractProductA* productA2 = factory2->createProductA();AbstractProductB* productB2 = factory2->createProductB();productA2->operationA();productB2->operationB();delete factory1;delete factory2;delete productA1;delete productB1;delete productA2;delete productB2;return 0;
}

运行结果:

Product A1 operation
Product B1 operation
Product A2 operation
Product B2 operation

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

抽象工厂模式的优点:

降低了客户端与具体产品的耦合度。

符合单一职责原则,每个具体工厂类只负责创建特定的产品。

隐藏了对象的创建过程,客户端不需要关心具体的对象创建细节,只需要通过工厂接口获取所需对象即可。

抽象工厂模式的缺点:

当产品族中需要增加新的产品时,既需要扩展抽象工厂的接口,又需要新增一个具体工厂类,大大增加了代码的维护成本。

当需要创建的产品种类非常多时,抽象工厂模式的类数量将急剧增加,导致系统难以维护和理解。

五、代码实战

模拟披萨的制作过程:

PizzaFactory:

NewYorkCheesePizza:bake() -> cut() -> box()

NewYorkPepperoniPizza:bake() -> cut() -> box()

ChicagoCheesePizza:bake() -> cut() -> box()

ChicagoPepperoniPizza:bake() -> cut() -> box()

#include <iostream>class Pizza {
public:virtual void bake() = 0;virtual void cut() = 0;virtual void box() = 0;
};class NewYorkCheesePizza : public Pizza {
public:void bake() override{std::cout << "Baking New York-style cheese pizza."<< std::endl;}void cut() override{std::cout << "Cutting New York-style cheese pizza."<< std::endl;}void box() override{std::cout << "Boxing New York-style cheese pizza."<< std::endl;}
};class NewYorkPepperoniPizza : public Pizza {
public:void bake() override{std::cout<< "Baking New York-style pepperoni pizza."<< std::endl;}void cut() override{std::cout<< "Cutting New York-style pepperoni pizza."<< std::endl;}void box() override{std::cout<< "Boxing New York-style pepperoni pizza."<< std::endl;}
};class ChicagoCheesePizza : public Pizza {
public:void bake() override{std::cout << "Baking Chicago-style cheese pizza."<< std::endl;}void cut() override{std::cout << "Cutting Chicago-style cheese pizza."<< std::endl;}void box() override{std::cout << "Boxing Chicago-style cheese pizza."<< std::endl;}
};class ChicagoPepperoniPizza : public Pizza {
public:void bake() override{std::cout << "Baking Chicago-style pepperoni pizza."<< std::endl;}void cut() override{std::cout<< "Cutting Chicago-style pepperoni pizza."<< std::endl;}void box() override{std::cout << "Boxing Chicago-style pepperoni pizza."<< std::endl;}
};class PizzaFactory {
public:virtual Pizza* createCheesePizza() = 0;virtual Pizza* createPepperoniPizza() = 0;
};class NewYorkPizzaFactory : public PizzaFactory {
public:Pizza* createCheesePizza() override{return new NewYorkCheesePizza();}Pizza* createPepperoniPizza() override{return new NewYorkPepperoniPizza();}
};class ChicagoPizzaFactory : public PizzaFactory {
public:Pizza* createCheesePizza() override{return new ChicagoCheesePizza();}Pizza* createPepperoniPizza() override{return new ChicagoPepperoniPizza();}
};int main()
{PizzaFactory* newYorkFactory= new NewYorkPizzaFactory();Pizza* newYorkCheesePizza= newYorkFactory->createCheesePizza();Pizza* newYorkPepperoniPizza= newYorkFactory->createPepperoniPizza();PizzaFactory* chicagoFactory= new ChicagoPizzaFactory();Pizza* chicagoCheesePizza= chicagoFactory->createCheesePizza();Pizza* chicagoPepperoniPizza= chicagoFactory->createPepperoniPizza();newYorkCheesePizza->bake();newYorkCheesePizza->cut();newYorkCheesePizza->box();newYorkPepperoniPizza->bake();newYorkPepperoniPizza->cut();newYorkPepperoniPizza->box();chicagoCheesePizza->bake();chicagoCheesePizza->cut();chicagoCheesePizza->box();chicagoPepperoniPizza->bake();chicagoPepperoniPizza->cut();chicagoPepperoniPizza->box();delete newYorkFactory;delete newYorkCheesePizza;delete newYorkPepperoniPizza;delete chicagoFactory;delete chicagoCheesePizza;delete chicagoPepperoniPizza;return 0;
}

运行结果:

Baking New York-style cheese pizza.
Cutting New York-style cheese pizza.
Boxing New York-style cheese pizza.
Baking New York-style pepperoni pizza.
Cutting New York-style pepperoni pizza.
Boxing New York-style pepperoni pizza.
Baking Chicago-style cheese pizza.
Cutting Chicago-style cheese pizza.
Boxing Chicago-style cheese pizza.
Baking Chicago-style pepperoni pizza.
Cutting Chicago-style pepperoni pizza.
Boxing Chicago-style pepperoni pizza.

六、参考阅读

https://www.fluentcpp.com/2022/04/06/design-patterns-vs-design-principles-abstract-factory/

https://www.geeksforgeeks.org/abstract-factory-pattern-c-design-patterns/

https://sourcemaking.com/design_patterns/abstract_factory/cpp/before-after

https://www.scaler.com/topics/design-patterns/creational-design-pattern/


http://www.ppmy.cn/devtools/138061.html

相关文章

8 设计模式之简单工厂模式

设计模式是软件开发中的一套通用解决方案&#xff0c;而简单工厂模式则是最基础、最常用的一种创建型模式。在这篇博客中&#xff0c;我将为大家详细介绍简单工厂模式的概念、优缺点&#xff0c;以及通过一个饮料制作的案例&#xff0c;帮助大家更好地理解和应用这种模式。 一、…

数字图像处理(4):FPGA中的定点数、浮点数

&#xff08;1&#xff09;定点数&#xff1a;小数点固定在数据的某一位置的数&#xff0c;可以分为定点整数和定点小数和普通定点数。定点数广泛应用于数字图像处理&#xff08;图像滤波、图像缩放&#xff09;和数字信号处理&#xff08;如FFT、定点卷积&#xff09;中。 定…

HTML飞舞的爱心

目录 系列文章 写在前面 完整代码 代码分析 写在后面 系列文章 序号目录1HTML满屏跳动的爱心&#xff08;可写字&#xff09;2HTML五彩缤纷的爱心3HTML满屏漂浮爱心4HTML情人节快乐5HTML蓝色爱心射线6HTML跳动的爱心&#xff08;简易版&#xff09;7HTML粒子爱心8HTML蓝色…

详解RabbitMQ在Ubuntu上的安装

​​​​​​​ 目录 Ubuntu 环境安装 安装Erlang 查看Erlang版本 退出命令 ​编辑安装RabbitMQ 确认安装结果 安装RabbitMQ管理界面 启动服务 查看服务状态 通过IP:port访问 添加管理员用户 给用户添加权限 再次访问 Ubuntu 环境安装 安装Erlang RabbitMq需要…

Node报错:npm error code ETIMEDOUT

1、报错详细信息 npm error code ETIMEDOUT npm error syscall connect npm error errno ETIMEDOUT npm error network request to https://registry.npmjs.org/express failed, reason: connect ETIMEDOUT 104.16.1.35:443 npm error network This is a problem related to ne…

矩阵重新排列——flip类函数

f l i p flip flip类函数可将向量或矩阵按某个方向旋转 对于向量 a a a&#xff0c; f l i p ( a ) flip(a) flip(a)表示将向量 a a a进行翻转 向量翻转不改变方向 对于矩阵 a a a 1. f l i p ( a , 1 ) 1.flip(a,1) 1.flip(a,1)和 f l i p u d ( a ) flipud(a) flipud(a)表示按…

LLamafactory API部署与使用异步方式 API 调用优化大模型推理效率

文章目录 背景介绍第三方大模型API 介绍LLamafactory 部署API大模型 API 调用工具类项目开源 背景介绍 第三方大模型API 目前&#xff0c;市面上有许多第三方大模型 API 服务提供商&#xff0c;通过 API 接口向用户提供多样化的服务。这些平台不仅能提供更多类别和类型的模型…

Paddle Inference部署推理(一)

一&#xff1a;Paddle Inference推理 简介 Paddle Inference 是飞桨的原生推理库&#xff0c;提供服务器端的高性能推理能力。由于 Paddle Inference 能力直接基于飞桨的训练算子&#xff0c;因此它支持飞桨训练出的所有模型的推理。 Paddle Inference 功能特性丰富&#xff…