设计模式----工厂模式

工厂模式

工厂模式即建立创建对象的工厂,实现创建者和调用者分离。

  • 简单工厂模式:该模式对对象创建管理方式最为简单,因为他简单的对不同类对象的创建进行了一层薄薄的封装。该模式通过向工厂传递类型来指定要创建的对象。

  • 工厂方法模式:将生成具体产品的任务分发给具体的产品工厂。

  • 抽象工厂模式:通过在AbstractFactory中增加创建产品的接口,并在具体子工厂中实现新加产品的创建。

简单工厂模式

简单工厂模式UML图
下面通过手机生产的过程进行理解:

#include <stdio.h>

typedef enum productType
{
    xiaomi,
    iphone,
    huawei
}PRODUCTTYPE;
class Phone
{
public:
    virtual void MakePhone() = 0;
};
class MI : public Phone
{
public:
    void MakePhone()
    {
        printf("make xiaomi phone\n");
    }
};
class IPHONE : public Phone
{
public:
    void MakePhone()
    {
        printf("make iphone phone\n");
    }
};
class HUAWEI : public Phone
{
public:
    void MakePhone()
    {
        printf("make huawei phone\n");
    }
};
class SimpleFactory
{
public:
    Phone *createPhone(PRODUCTTYPE type)
    {
        switch (type)
        {
        case xiaomi:
           return new MI();
        case iphone:
           return new IPHONE();
        case huawei:
           return new HUAWEI();
        default:
           return NULL;
        }
    }
};
int main()
{
    SimpleFactory *factory = new  SimpleFactory();
    Phone *phone1 =  factory->createPhone(huawei);
    if (phone1 != NULL)
        phone1->MakePhone();
    Phone *phone2 =  factory->createPhone(xiaomi);
    if (phone2 != NULL)
        phone2->MakePhone();
    Phone *phone3 =  factory->createPhone(iphone);
    if (phone3 != NULL)
        phone3->MakePhone();
    delete phone1;
    phone1 = NULL;
    delete phone2;
    phone2 = NULL;
    delete phone3;
    phone3 = NULL;
    return 0;
}

工厂方法模式

工厂方法模式UML图
简单工厂模式例子中,已经可以生产xiaomi,iphone和huawei三类产品。此时需要添加oppo产品。那么此时需要在产品枚举中添加新的产品类型,然后修改factory中的switch语句。这种改动量比较大,大工程中易产生错误,这种扩展方式是很糟糕的。并且由于对原始代码进行了修改,那么原来的测试工作就无效了,需要进行新的全覆盖测试。

工厂方法模式是在简单工厂模式的基础上,对工厂添加了一个抽象层。将工厂共同的动作抽象出来,而具体的实现由子类本身去实现,让子类决定生产什么样的产品。

应用场景

工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。核心工厂不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

1、设计初期,就考虑到产品在后期进行扩展的情况下,可以使用工厂方法模式。
2、产品结构复杂的请情况下,可以使用工厂方法模式。

设计模式在详细设计时就需要进行定夺,需要权衡很多方面的因素,不能为了使用而使用。

#include <stdio.h>

class Phone
{
public:
    virtual void MakePhone() = 0;
};
class MI : public Phone
{
public:
    void MakePhone()
    {
        printf("xiaomi phone\n");
    }
};
class HUAWEI : public Phone
{
public:
    void MakePhone()
    {
        printf("huawei phone\n");
    }
};
class Factory
{
public:
    virtual Phone *CreatePhone() = 0;
};
class MIFactory : public Factory
{
public:
    Phone *CreatePhone()
    {
        return new MI();
    }
};
class HUAWEIFactory : public Factory
{
public:
    Phone *CreatePhone()
    {
        return new HUAWEI();
    }
};
void main()
{
    Factory *MIfactory = new MIFactory();
    Phone *mi = MIfactory->CreatePhone();
    mi->MakePhone();
    Factory *HWfactory = new HUAWEIFactory();
    Phone *huawei = HWfactory->CreatePhone();
    huawei->MakePhone();
    if (MIfactory)
    {
        delete MIfactory;
        MIfactory = NULL;
    }
    if (mi)
    {
        delete mi;
        mi = NULL;
    }
    if (HWfactory)
    {
        delete HWfactory;
        HWfactory = NULL;
    }
    if (huawei)
    {
        delete huawei;
        huawei = NULL;
    }
}

抽象工厂模式

工厂方法模式,后期产品会越来越多,建立的工厂也会越来越多,工厂进行了增长,工厂变得凌乱而难于管理;由于工厂方法模式创建的对象都是继承于phone的,所以工厂方法模式中,每个工厂只能创建单一种类的产品,当需要生产一种全新的产品时(不继承自phone),工厂方法则心有余而力不足。

举个例子方理解:

一个显示器电路板厂商,旗下的显示器电路板种类有液晶和非液晶的;这个时候厂商建造两个工厂,A工厂负责生产液晶电路板;B工厂负责生产非液晶电路板;工厂一直这样运行着。但是有一天经理发现这届生产显示器的其他部分也能挣钱,所以,决定在建立两个厂C和D,C负责生产液晶显示其余部件;D负责生产非液晶显示器的其余部件。此时,旁边的参谋提出我们只需要在原有的A和B厂添加一条负责液晶和非液晶显示器其余部件的生产线。这样做只需要对原有的厂房进行扩大,而不需要增加新的厂房,一方面,方便管理;另一方面,生产液晶和非液晶显示器的技术人员对液晶显示器和液晶显示器的其他部件生产具有指导作用。
在软件的开过程中,工厂A和B就是工厂方法模式;再建立C和D,就是重复工厂方法模式,只是生产的产品不一样。这样做增加成本。在面向对象中,很注重对象的维护和管理,对象越多,就越难维护,成本也会增加。

抽象工厂模式UML图
抽象工厂模式,就好比是两个工厂方法模式的叠加。抽象工厂创建的是一系列相关的对象,其中创建的实现其实就是采用的工厂方法模式。在工厂factory中的每一个方法,就好比是一条生产线,而生产线实际需要生产什么养的产品,这是由factory1和factory2去决定的,这样便延迟了具体子类的实例化;同时集中化了生产线的管理,节省了资源的浪费。

使用场合:
工厂方法模式适用于产品种类结构单一的场合,为一类产品提供创建的接口;而抽象工厂方法适用于产品种类结构的场合,主要用于创建一组(有多个种类)相关的产品,为他们提供创建的接口;就是当具有多个抽象角色时,抽象工厂便可以排上用场。

#include <stdio.h>

class MI
{
public:
    virtual void MakePhone() = 0;
};
class RedMI : public MI
{
public:
    void MakePhone()
    {
        printf("redmi phone\n");
    }
};
class MIPro : public MI
{
public:
    void MakePhone()
    {
        printf("MIPro phone\n");
    }
};
class HUAWEI
{
public:
    virtual void MakePhone() = 0;
};
class Mate20 : public HUAWEI
{
public:
    void MakePhone()
    {
        printf("Mate20 Phone\n");
    }
};
class P30 : public HUAWEI
{
public:
    void MakePhone()
    {
        printf("P30 phone\n");
    }
};
class Factory
{
public:
    virtual MI* CreateMIPhone() = 0;
    virtual HUAWEI* CreateHWPhone() = 0;
};
class Factory1 : public Factory
{
public:
    MI* CreateMIPhone()
    {
        return new RedMI();
    }
    HUAWEI* CreateHWPhone()
    {
        return new Mate20();
    }
};
class Factory2 : public Factory
{
public:
    MI* CreateMIPhone()
    {
        return new MIPro();
    }
    HUAWEI* CreateHWPhone()
    {
        return new P30();
    }
};
void main()
{
    Factory *factoryObj1 = new Factory1();
    MI *mi1 = factoryObj1->CreateMIPhone();
    HUAWEI *hw1 = factoryObj1->CreateHWPhone();
    mi1->MakePhone();
    hw1->MakePhone();
    Factory *factoryObj2 = new Factory2();
    MI *mi2 = factoryObj2->CreateMIPhone();
    HUAWEI *hw2 = factoryObj2->CreateHWPhone();
    mi2->MakePhone();
    hw2->MakePhone();
    if (factoryObj1)
    {
        delete factoryObj1;
        factoryObj1 = NULL;
    }
    if (factoryObj2)
    {
        delete factoryObj2;
        factoryObj2 = NULL;
    }
    if (mi1)
    {
        delete mi1;
        mi1 = NULL;
    }
    if (mi2)
    {
        delete mi2;
        mi2 = NULL;
    }
    if (hw1)
    {
        delete hw1;
        hw1 = NULL;
    }
    if (hw2)
    {
        delete hw2;
        hw2 = NULL;
    }
}

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

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

相关文章

pip镜像源:清华镜像、阿里云镜像、豆瓣镜像与如何修改默认镜像源

pip镜像源&#xff1a;清华镜像、阿里云镜像、豆瓣镜像与如何修改默认镜像源 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;【Matplotlib之旅&#xff1a;零基础精通数据可视化】 &#x1f3c6;&#x1f3c6;关注博主&#xff0c;随时获取…

MyBatis关联查询和部分主配置文件映射文件

一、主配置文件 注意必须按规定的结构来配置 设置&#xff08;settings&#xff09; 这是 MyBatis 中极为重要的调整设置&#xff0c;它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。 看mybatis <settings><setting name"useGe…

善于利用GPT确实可以解决许多难题

当我设计一个导出Word文档的功能时&#xff0c;我面临了一个挑战。在技术选型时&#xff0c;我选择了poi-tl这个模板引擎&#xff0c;因为在网上看到了很多关于它的推荐。poi-tl可以根据模板快速导出Word文档。虽然之前没有做过类似的功能&#xff0c;而且项目中也没有用过&…

超声波清洗机大测评!希亦、洁盟、德国ODI、苏泊尔哪款性价比高?

眼镜逐渐已经成为现在大部分都离不开的一个视线辅助&#xff0c;但是很多朋友对于眼镜的清洗从开始佩戴眼镜时&#xff0c;就没有重视起来。其实清洗眼镜的方法有很多种&#xff0c;手动清洗跟超声波清洗机&#xff0c;后者的清洗相对来说会更加方便快捷一点&#xff0c;且清洗…

啄木鸟家庭维修|空调滤网多久清洗一次?

啄木鸟家庭维修范师傅解答 1、家用空调,如果不是在油烟较多或风沙较大的地区,是空调使用三百小时后就清洗一次过滤网。如果是处于油烟大或风沙大的地区,空调使用一百小时后就要清洗一次过滤网。 2、清洗空调滤网的时候先将空调的前盖打开,然后抠住面板的两边,用力拉开就可以看…

【算法 - 动态规划】最长公共子序列问题

在上两篇文章中&#xff0c;我们将 暴力递归 逐步修改成为 动态规划 &#xff0c;并介绍了有严格 dp表依赖 和无表依赖结构的解题方法。其中&#xff0c;前篇文章中的纸牌博弈问题属于 [L , R]上范围尝试模型。该模型给定一个范围&#xff0c;在该范围上进行尝试&#xff0c;套…

word文件中的图片压缩怎么操作?这几招教你轻松压缩

word文件中的图片压缩怎么操作&#xff1f;在日常办公中&#xff0c;我们经常需要在Word文档中插入图片来丰富内容。但有时候&#xff0c;插入的图片过大&#xff0c;不仅会增加文档的打开速度&#xff0c;还可能影响打印效果。那么&#xff0c;如何在保持图片质量的同时&#…

Android 面试问题 2024 版(其一)

Android 面试问题 2024 版&#xff08;其一&#xff09; 一、Java 和 Kotlin二、安卓组件三、用户界面 (UI) 开发四、安卓应用架构五、网络和数据持久性 一、Java 和 Kotlin Java 中的抽象类和接口有什么区别&#xff1f; 答&#xff1a;抽象类是不能实例化的类&#xff0c;它…

番茄工作法规则

番茄工作法规则: 一个番茄钟共30分钟&#xff0c;包括25分钟的工作时间和5分钟的休息时间。每完成四个番茄钟&#xff0c;就进行一次较长时间的休息&#xff0c;大约15-30分钟。一个番茄钟是不可分割的&#xff0c;一旦开启就必须坚持到底&#xff0c;如果打断&#xff0c;就视…

万界星空科技MES系统,实现数字化智能工厂

万界星空科技帮助制造型企业解决生产过程中遇到的生产过程不透明&#xff0c;防错成本高&#xff0c;追溯困难&#xff0c;品质不可控&#xff0c;人工效率低下&#xff0c;库存积压&#xff0c;交期延误等问题&#xff0c;从而达到“降本增效”的目标。打通各个信息孤岛&#…

英伟达推出ConsiStory免训练文生图模型;Sora物理悖谬的几何解释;Groq推出全球最快大模型

&#x1f989; AI新闻 &#x1f680; 英伟达推出ConsiStory免训练文生图模型 摘要&#xff1a;ConsiStory是一种免训练的一致性连贯文生成图模型&#xff0c;由英伟达和特拉维夫大学的研究人员开发。它解决了文生成图模型在生成内容一致性方面的两个主要问题。首先&#xff0…

顺序表漫谈

目录 ​编辑 1.线性表 2.顺序表 2.1概念及结构 2.2接口实现 1.顺序表的动态存储 2.顺序表初始化 3.顺序表销毁 4.顺序表增容 5.顺序表头插 6.顺序表尾插 7.顺序表头删 8.顺序表尾删 9.顺序表打印 10.顺序表在任意下标位置插入数据 11.顺序表删除任意下标位置的值…

VIO第2讲:IMU标定实验

VIO第2讲&#xff1a;IMU标定实验 文章目录 VIO第2讲&#xff1a;IMU标定实验5 IMU标定实验5.1 仿真数据产生5.1.1 c代码分析5.1.2 生成ros包数据 5.2 Allan方差实验&#xff08;港科大imu_utils&#xff09;5.2.1 安装5.2.2 运行 5.3 Allan方差实验&#xff08;matlab代码kali…

深度学习基础——GAN生成对抗网络

生成对抗网络(GAN)的简介 生成对抗网络GAN(Generative adversarial networks)是Goodfellow等在2014年提出的一种生成式模型。GAN在结构上受博弈论中的二元零和博弈(即二元的利益之和为零&#xff0c;一方的所得正是另一方的所失)的启发&#xff0c;系统由一个生成器和一个判别器…

pc微信逆向最新3.9.8.25版本

朋友让我开发一个关于微信的计数、统计、自动回复功能的机器人&#xff0c;主要是用在win10上面。 先看看结果&#xff01; 之前写过手机端的逆向&#xff0c;PC端逆向很长时间没写了&#xff0c;所以就在网上找了找。基本都是基于3.6&#xff0c;3.7&#xff0c;3.8版本的&a…

python读取txt文档数据并断言value值的大小

本文主要介绍&#xff1a;将接口返回的字典值{"x1":1,"x2":2....}手动存到txt&#xff0c;然后写代码断言每个value值是否都满足某个区间。运用到&#xff1a; 1、读取txt文件中的数据 2、pytest写用例格式 3、pytest.assume断言方式&#xff08;出现报错A…

C++力扣题目139--单词拆分 198--打家劫舍 213--打家劫舍II 337打家劫舍III

139.单词拆分 力扣题目链接(opens new window) 给定一个非空字符串 s 和一个包含非空单词的列表 wordDict&#xff0c;判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。 说明&#xff1a; 拆分时可以重复使用字典中的单词。 你可以假设字典中没有重复的单词。 …

【IEEE出版会议征稿】第七届计算机信息科学与应用技术国际学术会议(CISAT 2024)

【IEEE出版】第七届计算机信息科学与应用技术国际学术会议&#xff08;CISAT 2024&#xff09; 2024 7th International Conference on Computer Information Science and Application Technology 第七届计算机信息科学与应用技术国际学术会议&#xff08;CISAT 2024&#x…

低代码:更高效、简单的方式开发出专业级的项目

你是否为编程世界的各种挑战感到头痛&#xff1f;想要以更高效、简单的方式开发出专业级的项目&#xff1f; JNPF低代码工具正是你苦心寻找的产品&#xff01;它是一款专为稍微懂一点点编程思想的入门级人员设计的神奇工具&#xff0c;集成了丰富的功能和组件&#xff0c;让你轻…

[NOIP2016 普及组] 魔法阵(枚举的典型例题,值得一看)

在透视这道题之前&#xff0c;先用一道小题来练练手 密码锁&#xff08;这道题是我根据魔法阵改的&#xff09; Description 叮当在探索迷宫时被一扇大门挡住了去路&#xff0c;门上刻画了很多乱七八糟的数字&#xff0c;门被锁上了&#xff0c;无法打开&#xff0c;但是门上…