创建型模式 | 工厂模式

文章目录

  • 一、简单工厂
    • 1.1、原理
    • 1.2、核心角色
    • 1.3、UML类图
    • 1.4、代码实现
    • 1.5、总结
  • 二、工厂模式
    • 2.1、原理
    • 2.2、关键角色
    • 2.3、代码实现
    • 2.4、总结
  • 三、抽象工厂模式
    • 3.1、原理
    • 3.2、关键角色
    • 3.3、UML类图
    • 3.4、工厂模式与抽象工厂模式的区别

前言

工厂模式是最常用的设计模式之一,它提供了一种创建对象的最佳方式,在创建对象的时候,不会对客户端暴露创建逻辑,并且通过使用一个共同的接口来创建新的对象。工厂模式有三种,分别是简单工厂、工厂模式,抽象工厂

一、简单工厂

1.1、原理

通过传⼊相关的类型来返回相应的类对象,简单工厂模式看为工厂方法模式的一种特例。

1.2、核心角色

  • 简单工厂(SimpleFactory):根据类型创建类对象
  • 抽象产品(IProduct):产品接口,描述所有实例对象的公共接口
  • 具体产品(ConcreteProduct):实现产品接口

1.3、UML类图

下面以生成手机的代码为例,介绍简单工厂模式,UML类图如下:

在这里插入图片描述

1.4、代码实现

代码实现,如下:

#include <iostream>
using namespace std;

// 手机(抽象接口)
class IPhone {
public:
    virtual void Describe() = 0;
};

// 华为手机(具体产品)
class HuaweiPhone : public IPhone {
public:
    void Describe() {
        cout << "华为手机" << endl;
    }
};

// 苹果手机(具体产品)
class ApplePhone : public IPhone {
public:
    void Describe() {
        cout << "苹果手机" << endl;
    }
};

// 简单工厂
class PhoneFactory {
public:
    IPhone* Produce(string type) {
        IPhone *pPhone = nullptr;
        if (type == "Huawei") {
            pPhone = new HuaweiPhone;
        } else if (type == "Apple") {
            pPhone = new ApplePhone;
        }
        return pPhone;
    }
};

int main()
{
    // 简单工厂
    PhoneFactory factory;

    IPhone *pHuaweiPhone = factory.Produce("Huawei");
    IPhone *pApplePhone = factory.Produce("Apple");

    pHuaweiPhone->Describe();
    pApplePhone->Describe();

    return 0;
}

1.5、总结

简单工厂模式优点与缺点,如下:

优点:

  • 实现简单
  • 实现了对象创建与业务逻辑的分离

缺点:

  • 可扩展性差,如果新增手机产品,就需要修改PhoneFactory::Produce方法,违反了开放封闭原则

二、工厂模式

2.1、原理

定义创建对象抽象工厂,具体工厂负责实现抽象工厂接口,创建对应类型的对象

2.2、关键角色

  • 抽象工厂:定义了创建抽象产品的抽象工厂
  • 具体工厂:实现抽象工厂接口的具体工厂类,负责生产具体的产品
  • 抽象产品:产品接口,描述所有实例对象的公共接口
  • 具体产品:实现产品接口

2.3、代码实现

#include <iostream>
using namespace std;

// 手机(抽象接口)
class IPhone {
public:
    virtual void Describe() = 0;
};

// 华为手机(具体产品)
class HuaweiPhone : public IPhone {
public:
    void Describe() {
        cout << "华为手机" << endl;
    }
};

// 苹果手机(具体产品)
class ApplePhone : public IPhone {
public:
    void Describe() {
        cout << "苹果手机" << endl;
    }
};

// 抽象工厂
class IFactory {
public:
    virtual IPhone* Produce() = 0;
};

// 具体工厂(生产华为手机)
class HuaweiPhoneFactory : public IFactory {
public:
    IPhone* Produce() {
        return new HuaweiPhone;
    }
};

// 具体工厂(生产苹果手机)
class ApplePhoneFactory : public IFactory {
public:
    IPhone* Produce() {
        return new ApplePhone;
    }
};

int main()
{
    // 工厂对象
    HuaweiPhoneFactory huaweiFactory;
    ApplePhoneFactory appleFactory;

    IPhone *pHuaweiPhone = huaweiFactory.Produce();
    IPhone *pApplePhone = appleFactory.Produce();

    pHuaweiPhone->Describe();
    pApplePhone->Describe();

    return 0;
}

2.4、总结

工厂模式优点与缺点,如下:

优点:

  • 解决了简单工厂模式可扩展性差的问题,如果新增手机产品,新增一个产品类及对应的工厂类就可以,不会修改原有的代码,符合开放封闭原则

缺点:

  • 随着产品的增多,类的个数容易过多,增加复杂度
  • 具体工厂只能生产出一种产品(可以用抽象工厂模式解决)

三、抽象工厂模式

3.1、原理

抽象工厂模式在工厂方法模式的基础上进行进一步抽象。设想下面这种场景:在手机的基础上新增了Pad,要创建华为Phone华为Pad苹果Phone苹果Pad等产品,如果使用工厂模式,就要新增四个工厂类,使用工厂方法模式,创建了很多具体工厂类,而没有利用产品的商品族的概念。

抽象工厂模式是用于解决一类产品的创建问题(在上述场景中,可以把华为Phone华为Pad苹果Phone苹果Pad归纳为PhonePad这两类商品)

3.2、关键角色

抽象工厂模式与工厂模式的关键角色类似,有差异的地方在于抽象工厂类,如下:

  • 抽象工厂类:定义一组接口,用于创建多类产品;工厂方法的抽象工厂类,只定义了创建一类产品的接口

3.3、UML类图

使用抽象工厂类解决工厂方法遇到的两个问题,一是:只能生产一类产品的问题;二是:增加产品导致产品工厂类的个数容易过多的问题(解决新增Pad产品的问题,如果使用抽象工厂方法需要新增两个工厂类,而使用工厂方法需要四个工厂类),UML类图如下:

在这里插入图片描述

3.4、工厂模式与抽象工厂模式的区别

工厂模式主要解决一类产品的创建问题,抽象工厂模式主要是来解决多类(产品簇)产品创建问题。具体差异体现在抽象工厂角色上,工厂模式提供一个接口,创建一类产品;抽象工厂提供多个接口,可以创建多类产品。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

知识引导的分子生成扩散模型 - KGDiff 评测

一、背景介绍 KGDiff模型是一个基于口袋的知识引导的3D分子生成的扩散模型&#xff0c;来源于上海交通大学计算机学院涂仕奎教授的文章&#xff1a; 《KGDiff: towards explainable target-aware molecule generation with knowledge guidance》。文章链接&#xff1a;*KGDiff…

Qt QTableView和QStandardItemModel包含搜索出现的文本及隐藏顶层节点

前言 使用Qt进行开发时&#xff0c;树结构一般是使用QTreeWidget或使用QTreeViewQStandardItemModel结合。 查找 如果要进行查找树的所有项中&#xff0c;是否包含某文本&#xff0c;就需要遍历。 QTreeWidget查找 以下是使用QTreeWidget进行查找&#xff1a; 首先初始化一…

跟着仙凡兄学习编译Telegram vs2022 2024.1.11编译成功

编译Telegram 本人花了两天&#xff0c;问官方作者终于编译成功Telegram 运行环境&#xff1a;win11 vs2022 参见学习视频&#xff1a;【telegram编译成功&#xff0c;编译遇到的各种问题】https://www.bilibili.com/video/BV11c411x7jm?vd_sourcedf2e51268cc7412cc3937cf3df2…

如何构建Prompt,帮我生成QA,作为召回率检索的测试集?

最近在做搜索召回率的提升工作。粮草未动兵马先行&#xff01;在做之前应该先有一把尺子来衡量召回率的好坏。所以应该先构建测试数据集&#xff0c;然后去做标准化测试。 有了测试机集以后。再去做搜索优化&#xff0c;才能看出来效果。 当然可以选择一些开源的测试集。如果可…

【OpenCV学习笔记04】- 绘图功能

这是对于 OpenCV 官方文档的 GUI 功能的学习笔记。学习笔记中会记录官方给出的例子&#xff0c;也会给出自己根据官方的例子完成的更改代码&#xff0c;同样彩蛋的实现也会结合多个知识点一起实现一些小功能&#xff0c;来帮助我们对学会的知识点进行结合应用。 如果有喜欢我笔…

C++内存管理机制(侯捷)笔记1

C内存管理机制&#xff08;侯捷&#xff09; 本文是学习笔记&#xff0c;仅供个人学习使用。如有侵权&#xff0c;请联系删除。 参考链接 Youtube: 侯捷-C内存管理机制 Github课程视频、PPT和源代码: https://github.com/ZachL1/Bilibili-plus 第一讲primitives的笔记 截至…

【提示学习论文六】MaPLe: Multi-modal Prompt Learning论文原理

文章目录 MaPLe: Multi-modal Prompt Learning 多模式提示学习文章介绍动机MaPLe:Multi-modal Prompt Learning 模型结构1、Deep Language Prompting 深度语言提示2、Deep Vision Prompting 深度视觉提示3、Vision Language Prompt Coupling 视觉语言提示耦合提示耦合过程 实验…

使用MistNet在COCO128数据集上协作训练Yolo-v5

本案例介绍如何在MNIST手写数字分类场景中&#xff0c;使用名为MistNet的聚合算法训练联邦学习作业。数据分散在不同的地方&#xff08;如边缘节点、摄像头等&#xff09;&#xff0c;由于数据隐私和带宽的原因&#xff0c;无法在服务器上聚合。因此&#xff0c;我们不能将所有…

linux手动安装 vscode-server

适用场景 很多时候&#xff0c;我们需要在本机&#xff08;比如windows&#xff09;通过remote ssh访问远程服务器&#xff08;一般是ubuntu&#xff09;&#xff0c;但经常出现 vscode 一直连不上远程服务器的情况&#xff0c;看一下 log&#xff1a; 这个log表示远程服务器…

长尾分布定义,举个物种长尾分布和词频长尾分布的例子。

问题描述&#xff1a;长尾分布定义&#xff0c;举个物种长尾分布和词频长尾分布的例子。 问题解答&#xff1a; 长尾分布是一种概率分布的类型&#xff0c;它描述的是一种极端事件或者稀有事件的发生概率。具体来说&#xff0c;长尾分布描述的是少量的类别占据了大部分的样本…

uniapp 设置底部导航栏

uniapp 设置原生 tabBar 底部导航栏。 设置底部导航栏 一、创建页面&#xff0c;一定要在 pages.json 文件中注册。 二、在 pages.json 文件中&#xff0c;设置 tabBar 配置项。 pages.json 页面 {"pages": [...],"globalStyle": {...},"uniIdRout…

获取ffmpeg转码的实时进度

文章目录 前言一、需求二、实现获取 ffmpeg 转码的实时进度1、思路梳理2、源码修改 三、运行结果 前言 本文记录查看 ffmpeg 进行转码时的实时进度。所用的工程基于上个博客编译成功的工程&#xff1a;使用FFmpeg4.3.1的SDK官方开发包编译ffmpeg.c 一、需求 使用 ffmepg 对音…

二叉树题目:完全二叉树插入器

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;完全二叉树插入器 出处&#xff1a;919. 完全二叉树插入器 难度 6 级 题目描述 要求 完全二叉树是每一层&#xff08;除最后一层外&#xff09;都…

Word·VBA实现邮件合并

目录 制作邮件合并模板VBA实现邮件合并举例 之前写过的一篇使用《python实现word邮件合并》&#xff0c;本文为vba实现方法 制作邮件合并模板 域名可以使用中文&#xff0c;最终完成的word模板&#xff0c;wps操作步骤类似 VBA实现邮件合并 在Excel启用宏的工作表运行以下代…

攒机到底能省多少钱?

昨天弄好了攒机配置&#xff0c;今天要求配置一些更为实用的配置&#xff0c;只是作为一般办公&#xff0c;单位买进来的计算机都是联想&#xff0c;价格普遍在7000元以上&#xff0c;出于省钱和实用目的&#xff0c;今天搭配了一个组机方案。 上面的配置对付一般办公足够&…

查看进程对应的路径查看端口号对应的进程ubuntu 安装ssh共享WiFi设置MyBatis 使用map类型作为参数,复杂查询(导出数据)

Linux 查询当前进程所在的路径 top 命令查询相应的进程号pid ps -ef |grep 进程名 lsof -I:端口号 netstat -anp|grep 端口号 cd /proc/进程id cwd 进程运行目录 exe 执行程序的绝对路径 cmdline 程序运行时输入的命令行命令 environ 记录了进程运行时的环境变量 fd 目录下是进…

[HCTF 2018]Warmup

[HCTF 2018]Warmup wp 进入页面&#xff1a; 查看源码&#xff1a; 发现提示&#xff1a;source.php &#xff0c;直接访问&#xff0c;得到源代码&#xff1a; <?phphighlight_file(__FILE__);class emmm{public static function checkFile(&$page){$whitelist [&qu…

ROS-urdf集成gazebo

文章目录 一、URDF与Gazebo基本集成流程二、URDF集成Gazebo相关设置三、URDF集成Gazebo实操四、Gazebo仿真环境搭建 一、URDF与Gazebo基本集成流程 1.创建功能包 创建新功能包&#xff0c;导入依赖包: urdf、xacro、gazebo_ros、gazebo_ros_control、gazebo_plugins 2.编写URD…

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷⑨

2023年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项赛卷9 目录 需要竞赛软件包环境以及备赛资源可私信博主&#xff01;&#xff01;&#xff01; 2023年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项赛卷9 模块一 …

阿里云服务器的tcp端口无法访问(云服务厂家问题?)

问题->无法访问 阿里云服务器的tcp端口 最近一台阿里云服务器的一个端口61616无法访问&#xff0c;在服务器内用外网地ip发现无法访问&#xff0c;用内网ip访问是正常的&#xff0c;通过技术排查&#xff1a; 解决->无法访问 阿里云服务器的tcp端口 1 配置官网的安全组…