设计模式-工厂模式(Factory Pattern)

一、工厂模式说明

        工厂模式是一种创建型设计模式,它提供了一种将对象的创建与使用分离的方式。工厂模式通过引入一个公共的接口来创建对象,而不是通过直接调用构造函数来创建对象。这样做的好处是使得代码更加灵活,更容易维护和扩展。

        工厂模式通常包含以下几个角色:

        产品(Product): 产品是工厂模式所创建的对象。它可以是一个接口、抽象类或者具体类,用来描述工厂创建的对象所具有的特性和行为。

        工厂接口(Factory Interface): 工厂接口是用来创建产品对象的接口,它定义了一个或多个工厂方法用来创建产品。通常情况下,工厂接口是一个抽象类或者接口,其中的工厂方法可以是抽象方法或者默认实现方法。

        具体工厂(Concrete Factory): 具体工厂是工厂模式的实现者,它实现了工厂接口,负责创建具体的产品对象。每个具体工厂类通常都与一个特定的产品相关联,用来创建该产品的实例。

        客户端(Client): 客户端是使用工厂模式的地方,它通过工厂接口来创建产品对象,而不需要知道具体的产品类。客户端通常只与工厂接口和产品接口交互,而不直接依赖具体的产品类。

二、工厂模式应用

        在实际应用中的例子时,有几个常见的场景:

        数据库连接池: 在大多数现代应用程序中,需要频繁地与数据库进行交互。为了提高性能和效率,通常会使用数据库连接池。连接池是一组预先创建的数据库连接,可以在需要时重新使用。工厂模式可用于创建这些数据库连接,以便统一管理连接的创建和销毁。例如,可以使用工厂方法模式创建不同类型的数据库连接对象,如 MySQL 连接、PostgreSQL 连接等。

        日志记录器: 许多应用程序需要记录事件和错误信息以便后期分析和调试。日志记录器是用于记录这些信息的工具。工厂模式可用于创建不同类型的日志记录器,如文件日志记录器、数据库日志记录器、控制台日志记录器等。根据应用程序的需求,可以选择合适的日志记录器类型。例如,可以使用抽象工厂模式来创建不同类型的日志记录器对象,并使用配置文件或其他参数来确定要创建的日志记录器类型。

        UI控件库: 在图形用户界面(GUI)应用程序中,UI控件库用于创建和管理各种用户界面元素,如按钮、文本框、标签等。工厂模式可用于创建这些UI控件。例如,可以使用简单工厂模式创建不同类型的UI控件对象,并提供统一的接口来访问这些控件。这样可以降低客户端代码与具体控件实现之间的耦合,并提高代码的灵活性和可维护性。

        加密算法库: 在安全领域中,加密算法是非常重要的组成部分。工厂模式可用于创建不同类型的加密算法对象,如对称加密算法、非对称加密算法等。例如,可以使用工厂方法模式创建不同类型的加密算法对象,并提供统一的接口来加密和解密数据。这样可以方便地切换和使用不同类型的加密算法,而不影响客户端代码。

        游戏开发: 在游戏开发中,经常需要创建各种游戏对象,如角色、道具、怪物等。工厂模式可用于创建这些游戏对象。例如,可以使用工厂方法模式创建不同类型的游戏对象,并提供统一的接口来处理游戏逻辑。这样可以方便地扩展和修改游戏中的对象,而不需要修改客户端代码。

三、 工厂模式的实现

(一) 简单工厂模式

        简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,它提供了一个专门的工厂类用于创建对象,而不需要将对象的创建逻辑暴露给客户端。简单工厂模式通过将对象的创建过程封装在工厂类中,使得客户端无需知道具体的实例化逻辑,只需要通过工厂类来获取所需的对象。

        简单工厂模式由三个主要组成部分构成:

        工厂类(Factory Class):工厂类负责创建对象的实例。通常包含一个静态方法或成员方法,根据客户端的请求创建并返回具体的对象实例。客户端通过调用工厂类的方法获取所需的对象。

        抽象产品类(Abstract Product Class):抽象产品类定义了所创建的对象的通用接口,客户端通过该接口与具体产品进行交互。工厂类负责创建的对象都是抽象产品类的子类对象。

        具体产品类(Concrete Product Class):具体产品类是抽象产品类的具体实现,它实现了抽象产品类定义的接口,并提供了具体的功能和行为。

#include <iostream>
#include <memory>// 抽象产品类
class Product {
public:virtual void showInfo() = 0;virtual ~Product() {}
};// 具体产品接口1:颜色属性 <- 这边是为了实现 接口隔离原则 
class Colorable {
public:virtual void setColor(const std::string& color) = 0;virtual std::string getColor() const = 0;virtual ~Colorable() {}
};// 具体产品类:电子产品
class ElectronicProduct : public Product {
public:void showInfo() override {std::cout << "Electronic Product: Smart Phone\n";}
};// 具体产品类:服装
class ClothingProduct : public Product, public Colorable {
private:std::string color;
public:void showInfo() override {std::cout << "Clothing Product: T-Shirt\n";}void setColor(const std::string& color) override {this->color = color;}std::string getColor() const override {return color;}
};// 具体产品类:食品
class FoodProduct : public Product {
public:void showInfo() override {std::cout << "Food Product: Chocolate\n";}
};// 简单工厂类
class ProductFactory {
public:// 根据传入的参数创建不同类型的产品对象std::unique_ptr<Product> createProduct(char type) {switch (type) {case 'E':return std::make_unique<ElectronicProduct>();case 'C':return std::make_unique<ClothingProduct>();case 'F':return std::make_unique<FoodProduct>();default:std::cerr << "Invalid product type\n";return nullptr;}}
};int main() {// 使用简单工厂创建不同类型的商品对象ProductFactory factory;std::unique_ptr<Product> product1 = factory.createProduct('E');if (product1) {product1->showInfo();}std::unique_ptr<Product> product2 = factory.createProduct('C');if (product2) {product2->showInfo();Colorable* colorableProduct = dynamic_cast<Colorable*>(product2.get());if (colorableProduct) {colorableProduct->setColor("Red");std::cout << "Color: " << colorableProduct->getColor() << std::endl;}}std::unique_ptr<Product> product3 = factory.createProduct('F');if (product3) {product3->showInfo();}return 0;
}

(二) 工厂方法模式

        工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但是将具体对象的创建延迟到了子类中。这样,工厂方法模式允许一个类的实例化延迟到子类中,从而使得一个类的实例化与子类的具体实现解耦。

        工厂方法模式由四个主要组成部分构成:

        抽象产品类(Abstract Product Class):定义了工厂方法所创建的对象的接口,客户端通过该接口与具体产品进行交互。

        具体产品类(Concrete Product Class):具体产品类是抽象产品类的实现,它定义了具体产品的属性和行为。

        抽象工厂类(Abstract Factory Class):抽象工厂类定义了一个抽象的工厂方法,该方法返回一个抽象产品类的实例。该类可以是抽象类或接口。

        具体工厂类(Concrete Factory Class):具体工厂类是抽象工厂类的实现,它实现了抽象工厂类定义的工厂方法,负责创建具体的产品对象。

#include <iostream>
#include <memory>// 抽象产品类
class Product {
public:virtual void showInfo() = 0;virtual ~Product() {}
};// 具体产品类:电子产品
class ElectronicProduct : public Product {
public:void showInfo() override {std::cout << "Electronic Product: Smart Phone\n";}
};// 具体产品类:服装
class ClothingProduct : public Product {
public:void showInfo() override {std::cout << "Clothing Product: T-Shirt\n";}
};// 具体产品类:食品
class FoodProduct : public Product {
public:void showInfo() override {std::cout << "Food Product: Chocolate\n";}
};// 抽象工厂类
class ProductFactory {
public:virtual std::unique_ptr<Product> createProduct() = 0;virtual ~ProductFactory() {}
};// 具体工厂类:电子产品工厂
class ElectronicProductFactory : public ProductFactory {
public:std::unique_ptr<Product> createProduct() override {return std::make_unique<ElectronicProduct>();}
};// 具体工厂类:服装工厂
class ClothingProductFactory : public ProductFactory {
public:std::unique_ptr<Product> createProduct() override {return std::make_unique<ClothingProduct>();}
};// 具体工厂类:食品工厂
class FoodProductFactory : public ProductFactory {
public:std::unique_ptr<Product> createProduct() override {return std::make_unique<FoodProduct>();}
};int main() {// 使用具体工厂类来创建产品对象std::unique_ptr<ProductFactory> electronicFactory = std::make_unique<ElectronicProductFactory>();std::unique_ptr<Product> product1 = electronicFactory->createProduct();product1->showInfo();std::unique_ptr<ProductFactory> clothingFactory = std::make_unique<ClothingProductFactory>();std::unique_ptr<Product> product2 = clothingFactory->createProduct();product2->showInfo();std::unique_ptr<ProductFactory> foodFactory = std::make_unique<FoodProductFactory>();std::unique_ptr<Product> product3 = foodFactory->createProduct();product3->showInfo();return 0;
}

(三) 抽象工厂模式

        抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一个接口用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。抽象工厂模式通过引入抽象工厂类和具体工厂类来实现对象的创建,使得客户端可以从抽象工厂类中获取具体工厂类的实例,进而创建所需的产品对象。

        抽象工厂模式由四个主要组成部分构成:

        抽象产品类(Abstract Product Class):定义了工厂方法所创建的对象的接口,客户端通过该接口与具体产品进行交互。

        具体产品类(Concrete Product Class):具体产品类是抽象产品类的实现,它定义了具体产品的属性和行为。

        抽象工厂类(Abstract Factory Class):抽象工厂类定义了一个抽象的工厂方法,该方法返回一个抽象产品类的实例。抽象工厂类可以是一个接口或者抽象类。

        具体工厂类(Concrete Factory Class):具体工厂类是抽象工厂类的实现,它实现了抽象工厂类定义的工厂方法,并负责创建具体的产品对象。

#include <iostream>
#include <memory>// 抽象产品类
class ElectronicProduct {
public:virtual void showInfo() = 0;virtual ~ElectronicProduct() {}
};class ClothingProduct {
public:virtual void showInfo() = 0;virtual ~ClothingProduct() {}
};// 具体产品类:手机
class SmartPhone : public ElectronicProduct {
public:void showInfo() override {std::cout << "Smart Phone\n";}
};// 具体产品类:T恤
class TShirt : public ClothingProduct {
public:void showInfo() override {std::cout << "T-Shirt\n";}
};// 抽象工厂类
class AbstractFactory {
public:virtual std::unique_ptr<ElectronicProduct> createElectronicProduct() = 0;virtual std::unique_ptr<ClothingProduct> createClothingProduct() = 0;virtual ~AbstractFactory() {}
};// 具体工厂类:电子产品工厂
class ElectronicFactory : public AbstractFactory {
public:std::unique_ptr<ElectronicProduct> createElectronicProduct() override {return std::make_unique<SmartPhone>();}std::unique_ptr<ClothingProduct> createClothingProduct() override {// 在这个工厂中,我们无法创建服装产品,因此返回 nullptrreturn nullptr;}
};// 具体工厂类:服装工厂
class ClothingFactory : public AbstractFactory {
public:std::unique_ptr<ElectronicProduct> createElectronicProduct() override {// 在这个工厂中,我们无法创建电子产品,因此返回 nullptrreturn nullptr;}std::unique_ptr<ClothingProduct> createClothingProduct() override {return std::make_unique<TShirt>();}
};int main() {// 创建电子产品工厂并使用std::unique_ptr<AbstractFactory> electronicFactory = std::make_unique<ElectronicFactory>();std::unique_ptr<ElectronicProduct> electronicProduct = electronicFactory->createElectronicProduct();if (electronicProduct) {electronicProduct->showInfo();}// 创建服装工厂并使用std::unique_ptr<AbstractFactory> clothingFactory = std::make_unique<ClothingFactory>();std::unique_ptr<ClothingProduct> clothingProduct = clothingFactory->createClothingProduct();if (clothingProduct) {clothingProduct->showInfo();}return 0;
}

四、工厂模式总结

工厂模式类型

优点

缺点

适用场景

简单工厂模式

(Simple Factory Pattern)

- 实现简单易懂

- 将对象创建和使用解耦

- 违反开闭原则

- 工厂类集中了所有产品的创建逻辑

- 产品较少

- 产品不经常变化

工厂方法模式

(Factory Method Pattern)

- 符合开闭原则

- 延迟对象的创建

- 增加灵活性

- 每次新增产品都需要编写一个具体工厂类

- 产品具有相同接口

- 创建逻辑相对复杂的情况

抽象工厂模式

(Abstract Factory Pattern)

- 将对象创建和使用解耦

- 符合开闭原则

- 新增产品族比较困难

- 需要修改抽象工厂接口及实现类

- 创建一系列相关产品对象

- 保证产品族一致性

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

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

相关文章

第3部分 原理篇2去中心化数字身份标识符(DID)(2)

3.2.2. DID相关概念 3.2.2.1. 去中心化标识符 (Decentralized identifier&#xff0c;DID) 本聪老师&#xff1a;DID有两个含义&#xff0c;一是Decentralized identity&#xff0c;就是去中心化身份&#xff0c;是广泛意义的DID。另外一个是Decentralized identifier&#xf…

Web性能优化-浏览器工作原理-MDN文档学习笔记

浏览器工作原理 查看更多学习笔记&#xff1a;GitHub&#xff1a;LoveEmiliaForever MDN中文官网 导航 导航是加载 web 页面的第一步&#xff1a;输入 URL、点击一个链接、提交表单等等 DNS查询 导航的第一步是要去寻找页面资源的位置 例如访问https://example.com&#x…

如何解决DNS解析错误故障

DNS解析错误会导致将一个域名解析为错误的IP地址&#xff0c;或者根本无法确定某个域名对应的IP地址&#xff0c;从而无法通过域名访问相应的站点&#xff0c;形成DNS解析故障。最常见的症状是访问站点对应的IP地址没有问题&#xff0c;但访问其域名时却出现错误。 DNS解析异常…

qt-动画圆圈等待-LED数字

qt-动画圆圈等待-LED数字 一、演示效果二、关键程序三、下载链接 一、演示效果 二、关键程序 #include "LedNumber.h" #include <QLabel>LEDNumber::LEDNumber(QWidget *parent) : QWidget(parent) {//设置默认宽高比setScale((float)0.6);//设置默认背景色se…

【深入了解TensorFlow】TensorFlow的安装与配置

【深入了解TensorFlow】TensorFlow的安装与配置 TensorFlow的安装与配置准备就绪:开始前的准备工作1. 确定您的硬件和操作系统2. 选择安装方式3. 创建虚拟环境(可选)安装TensorFlow使用pip安装使用conda安装从源代码编译安装配置TensorFlow导入TensorFlow模块检查安装是否成…

Oracle 表被删除或重命名后账户间的授权与同义词关系

Oracle 表被删除或重命名后账户间的授权与同义词关系 情景一、 当数据表删除后 数据表被删除后&#xff0c;同义词还是存在的&#xff0c;可以查看当前用户下查看同义词&#xff1a; -- 查看当前用户下的同义词 select * from user_synonyms但授权关系不在了&#xff0c;若重…

10 个 Linux 中超方便的 Bash 别名

1、 你有几次遇到需要解压 .tar 文件但无法记住所需的确切参数&#xff1f;别名可以帮助你&#xff01;只需将以下内容添加到 .bash_profile 中&#xff0c;然后使用 untar FileName 解压缩任何 .tar 文件。 alias untartar -zxvf 2、 下载文件时&#xff0c;如果出现问题想要…

websocket与Socket的区别

概念讲解 网络&#xff1a;通俗意义上&#xff0c;也就是连接两台计算器 五层网络模型&#xff1a;应用层、传输层、网络层、数据链路层、物理层 应用层 (application layer)&#xff1a;直接为应用进程提供服务。应用层协议定义的是应用进程间通讯和交互的规则&#xff0c;不…

明明正常,却不停return

明明正常&#xff0c;却不停return if(!is); { return ; } 熬人

应急响应速查

最重要的&#xff1a;我是谁&#xff1f;我在哪&#xff1f;别人怎么进来的&#xff1f;我就是这个被挖矿被勒索的电脑。 分析项 &#xff1a; 一、了解大概的被入侵系统情况&#xff1a; 发现时间&#xff1f;怎么发现的&#xff1f;这台机器有没有人运维&#xff1f;平时还…

排序第三篇 直接插入排序

插入排序的基本思想是&#xff1a; 每次将一个待排序的记录按其关键字的大小插入到前面已排好序的文件中的适当位置&#xff0c; 直到全部记录插入完为止。 一 简介 插入排序可分为2类 本文介绍 直接插入排序 它的基本操作是&#xff1a; 假设待排充序的记录存储在数组 R[1……

电路设计(27)——交通信号灯的multisim仿真

1.功能要求 使用数字芯片设计一款交通信号灯&#xff0c;使得&#xff1a; 主干道的绿灯时间为60S&#xff0c;红灯时间为45S 次干道的红灯时间为60S&#xff0c;绿灯时间为45S 主、次干道&#xff0c;绿灯的最后5S内&#xff0c;黄灯闪烁 使用数码管显示各自的倒计时时间。 按…

JavaScript 数组、遍历

数组 多维数组&#xff1a;数组里面嵌套 一层数组为二维数组。一维数组的使用频率是最高的。 如果数组访问越界会返回undefined。 数组遍历 数组方法Array.isArray() 这个方法可以去判定一个内容是否是数组。

AndroidStudio 2024-2-21 Win10/11最新安装配置(Kotlin快速构建配置,gradle镜像源)

AndroidStudio 2024 Win10/11最新安装配置 教程目的&#xff1a; (从安装到卸载) &#xff0c;针对Kotlin开发配置&#xff0c;gradle-8.2-src/bin下载慢&#xff0c;以及Kotlin构建慢的解决 好久没玩AS了,下载发现装个AS很麻烦,就觉得有必要出个教程了(就是记录一下:嘻嘻) 因…

把一个对象变成可迭代对象的两种方法,使用Symbol.iterator 和生成器Generator

方法一&#xff1a;自定义Symbol.iterator属性 如果对象拥有[Symbol.iterator] 方法&#xff0c;改方法返回一个迭代器对象&#xff0c;就可以称之为可迭代对象&#xff0c;注意迭代器是一个有 next 方法的对象 步骤如下 实现一个Symbol.iterator 键值是一个函数&#xff0c;…

java 时间格式 YYYY 于yyyy的区别

java formatDate 时间时&#xff0c;经常需要输入格式比如 YYYYMMDD,yyyyMMdd 这两个是有区别的 具体每个参数可以看下面

igolang学习1,dea的golang-1.22.0

参考&#xff1a;使用IDEA配置GO的开发环境备忘录-CSDN博客 1.下载All releases - The Go Programming Language (google.cn) 2.直接next 3.window环境变量配置 4.idea的go插件安装 5.新建go项目找不到jdk解决 https://blog.csdn.net/ouyang111222/article/details/1361657…

代码随想录算法训练营第40天| 343. 整数拆分、96.不同的二叉搜索树

343. 整数拆分 完成 思路&#xff1a; dp数组存放正整数i拆分后的乘积最大值&#xff1b;i可以拆分为j和i-j&#xff0c;也可以是j和dp[i-j]。 代码 class Solution {public int integerBreak(int n) {int[] dp new int[n1];dp[2] 1;// 推导i的拆分乘积最大值for (int i …

【js】无限虚拟列表的原理及实现

什么是虚拟列表 虚拟列表是长列表按需显示思路的一种实现&#xff0c;即虚拟列表是一种根据滚动容器元素的可视区域来渲染长列表数据中某一个部分数据的技术。 简而言之&#xff0c;虚拟列表指的就是「可视区域渲染」的列表。有三个概念需要了解一下&#xff1a; 视口容器元…

【linux】linux查看某个已经启动进程的环境变量及命令行信息 /proc/${pid}/environ cmdline

随便找一个进程 yeqiangyeqiang-MS-7B23:~$ ps aux | grep Vir yeqiang 3538 0.4 0.6 1797056 210332 ? Sl 08:38 0:06 /usr/lib/virtualbox/VirtualBox 查看命令行 yeqiangyeqiang-MS-7B23:~$ strings /proc/3538/cmdline /usr/lib/virtualbox/VirtualBox …