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

server/2024/11/29 10:10:27/

一、抽象工厂模式的定义

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

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

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

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

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

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

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

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

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

二、抽象工厂模式的结构

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

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/server/145880.html

相关文章

python: generator model using mysql9.0 or postgreSQL 17.0

mysql 9.0: # encoding: utf-8 # 版权所有 2024 ©涂聚文有限公司 # 许可信息查看&#xff1a;言語成了邀功盡責的功臣&#xff0c;還需要行爲每日來值班嗎 # 描述&#xff1a; # Author : geovindu,Geovin Du 涂聚文. # IDE : PyCharm 2023.1 python 3.11 # OS …

【Ant Design Vue】表单校验 rules 不起作用

先展示修改后可校验的完整 demo<template><div class"rules-container"><a-form-modelref"formRef":model"formState":rules"rules":label-col"labelCol":wrapper-col"wrapperCol"><a-form-…

实验六 用MATLAB设计IIR数字滤波器

例题 例2-1 采用脉冲响应不变法设计一个巴特沃斯数字低通滤波器 要求&#xff1a;ωp0.25π&#xff0c;Rp1dB&#xff1b;ωs0.4π&#xff0c;As15dB&#xff0c;滤波器采样频率Fs2000Hz。 wp0.25*pi; %滤波器的通带截止频率 ws0.4*pi; %滤波器的阻…

【Axure高保真原型】视频列表播放器_横向翻页效果

今天和大家分享视频列表播放器_横向翻页效果的原型模板&#xff0c;我们点击视频列表里的视频&#xff0c;可以在真实的播放该视频&#xff0c;每个视频都可以点击查看&#xff0c;如果视频菜单太多&#xff0c;我们也可以通过点击左右按钮翻页查看。这个视频列表的模板是用中继…

数据库(MySQL黑马)

基础篇 MySQL概述 数据库概述 数据库相关概念 主流的关系型数据库管理系统 MySQL数据库的安装与启动 下载&#xff1a;MySQL :: MySQL Community Downloads 安装步骤 MySQL―8.0.40超详细保姆级安装教程_mysql8.0.40安装教程-CSDN博客文章浏览阅读1k次。_mysql8.0.40安装教…

信息技术与数据安全:打造高效、安全的数据处理系统

信息技术与数据安全&#xff1a;打造高效、安全的数据处理系统 在当今这个信息化高速发展的时代&#xff0c;数据已成为企业运营和决策的核心资源。随着大数据、云计算、人工智能等信息技术的飞速发展&#xff0c;数据处理能力得到了前所未有的提升&#xff0c;但同时也对数据…

itertools模块常用方法

count(start0, step1) import itertools# 创建一个从start开始&#xff0c;以step为步长的无限迭代器 for i in itertools.count(1, 2):if i > 10:breakprint(i) # output: # 1 # 3 # 5 # 7 # 9cycle(iterable) import itertools# 对一个可迭代对象进行无限循环 count 0 …

JS异步进化与Promise

JavaScript 是单线程的&#xff0c;但它并不是无法处理异步操作。相反&#xff0c;JavaScript 的单线程特性和其事件循环机制使得它在处理异步任务方面非常高效 回调函数(Callback Functions) 一开始JS使用回调的形式来处理异步的结果,但是异步的弊端很大 例如:无法更好的处理…