一、简介

工厂模式属于一种创建型模式,它提供一种创建对象的最佳方式,对外不暴露对象的创建,并且通过一个共同的接口获取对象指针。

就像一个工厂根据消费者的需求生产不同的产品,但是并不需要对消费者开放生产方式。消费者只需要使用产品就好,并不需要知晓产品的生成。

适用场景:一般需要生成复杂对象的时候使用工厂模式。但是如果是比较简单的对象,则最好不要使用工厂模式,因为工厂模式需要创建工厂类,增加了系统的复杂性。

二、简单工厂模式

简单工厂模式,封装工厂类,用来提供创建目标对象的方法。

以服装厂为例。假设服装厂可以生产T恤和裤子两种产品。

1、先创建一个衣服的抽象类

//衣服抽象类
class Clothe
{
public:virtual void Show() = 0;virtual ~Clothe() {}
};

2、然后,我们创建具体的产品:T恤产品和裤子产品。此类继承于Clothe

//T恤衫产品具体类
class TShirt : public Clothe
{
public:void Show(){cout << "This is T-shirt!" << endl;}
};//裤子产品具体类
class Pants : public Clothe
{
public:void Show(){cout << "This is Pants!" << endl;}
};

3、创建工厂,此工厂会根据“客户”的需求,生产对应的产品(即实例化相应的对象)

typedef enum
{T_SHIRT,PANTS
}CLOTHE_TYPE;//服装工厂
class ClotheFactory
{
public:Clothe* CreateClothe(CLOTHE_TYPE myType){switch (myType){case CLOTHE_TYPE::T_SHIRT:return new TShirt();case CLOTHE_TYPE::PANTS:return new Pants();default:return nullptr;}return nullptr;}virtual ~ClotheFactory() {}
};

4、最后,我们可以调用这个工厂生产产品了。

需要注意的是,因为clothe其实是new出来的,使用完后需要delete释放掉。

int main()
{//调用工厂生产裤子ClotheFactory factory;Clothe* clothe = factory.CreateClothe(CLOTHE_TYPE::PANTS);clothe->Show();//new的对象使用完后需要deletedelete clothe;clothe = nullptr;system("pause");return 0;
}

从简单工厂模式的描述,我们可以看到工厂直接提供了实例化“产品”的方法,即CreateClothe,虽然保护了对象实例化的过程,但是不符合面向对象编程的开闭原则。

开闭原则:在面向对象领域,开闭原则规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”。

假如工厂还需要再增加产品,对于简单工厂模式来说,就需要修改CreateClothe的实现,这违背了开闭原则。所以我们可以使用下面的工厂方法模式来解决这个问题。

三、工厂方法模式

使用抽象类接管工厂的管理,额外定义各个产品单独实现的具体工厂,这些工厂继承了抽象工厂,用来实现具体对象的创建。

以服装厂为例,可以把抽象类理解为一家服装厂公司,这家公司旗下目前有2家工厂,一间只生产T恤,一间只生产裤子。如果有新类型的产品裙子需要增加,就再增加一间工厂,只用来生产裙子,这样就不用改变原来2个工厂的生产内容了,符合开闭原则。

具体代码示例

1、先创建一个衣服的抽象类,此类并不会具体“生产”产品,代码同简单工厂模式

2、然后,我们创建具体的产品:T恤产品和裤子产品,代码同简单工厂模式

3、创建一个抽象类,作为“服装厂公司”,此类作为接口,不再具体实例化产品

//服装工厂
class ClotheFactory
{
public:virtual Clothe* CreateClothe() = 0;
};

4、定义生产各个产品的工厂

//T恤工厂,只用来生产T恤
class TShirtFactory : public ClotheFactory
{
public:virtual Clothe* CreateClothe(){return new TShirt();}
};//裤子工厂,只用来生产裤子
class PantsFactory : public ClotheFactory
{
public:virtual Clothe* CreateClothe(){return new Pants();}
};

5、可以开始生产了

int main()
{//调用工厂生产T恤ClotheFactory* factory = new TShirtFactory();if (nullptr != factory){Clothe* clothe = factory->CreateClothe();if (nullptr != clothe){clothe->Show();//new的对象使用完后需要deletedelete clothe;clothe = nullptr;}}system("pause");return 0;
}

【注】如果这家工厂公司需要增加产品裙子,则再增加一个生产裙子的工厂就可以。即再增加如下代码即可

//裙子产品
class Skirt : public Clothe
{
public:void Show(){cout << "This is Skirt!" << endl;}
};//裙子工厂,只用来生产裙子
class SkirtFactory : public ClotheFactory
{
public:virtual Clothe* CreateClothe(){return new Skirt();}
};

可见,工厂方法模式对于简单方法模式来说,增加了系统的复杂度。因为每增加一个产品都要新增一个具体工厂类。对于我们日常写项目来说,需要根据具体情况做取舍。

工厂方法模式还存在一个问题,我们根据抽象工厂ClotheFactory只能去实例化一种类型的产品,即可以实例化继承于Clothe类的TShirt和Pants。而无法创建其他类型(即继承于其他抽象产品类的)对象。

比如,由于疫情来袭,这家服装厂公司决定开辟一条口罩的生产线,用于生产例如N95口罩、医用外科口罩等。由此我们要定义

A、一个口罩抽象产品类

//口罩抽象类
class Mask
{
public:virtual void equip() = 0;virtual ~Mask() {};
};

B、N95口罩和外科口罩具体类

//N95口罩具体类
class N95Mask : public Mask
{virtual void equip(){cout << "equipped N95 mask!" << endl;}
};//外科口罩具体类
class SurgicalMask : public Mask
{virtual void equip(){cout << "equipped surgical mask!" << endl;}
};

但是在创建工厂的时候,我们犯了难,现有工厂是无法扩展出对口罩的生产创建的。现有的工厂抽象类ClotheFactory中没有对Mask类的创建方法,所以无论如何,我们都需要在工厂抽象类中修改出对Mask产品的创建方法,即我们需要违背开闭原则,使用下面介绍的抽象工厂模式来解决这个问题。

四、抽象工厂模式

抽象工厂模式适用于需要管理不同类型的类对象的实例化的情况。是工厂方法模式的扩展。抽象工厂模式不符合开闭原则。

以上诉问题例,如果这家工厂打算扩展口罩的生产业务。则需要

1、创建口罩产品抽象类,代码见上诉A

2、创建具体口罩产品的具体实现类,代码见上诉B

3、修改工厂抽象类,此类需要增加生成Mask的方法CreateMask,所以再使用ClotheFactory作为类名不是很合适,改成Factory

//工厂抽象类
class Factory
{
public:virtual Clothe* CreateClothe(CLOTHE_TYPE type) = 0;virtual Mask* CreateMask(MASK_TYPE type) = 0;
};

4、生产工厂具体类,具体实现根据传入参数生成对应的clothe或mask

//生产工厂具体类
class ProduceFactory : public Factory
{
public:virtual Clothe* CreateClothe(CLOTHE_TYPE type){switch (type){case CLOTHE_TYPE::T_SHIRT:return new TShirt();case CLOTHE_TYPE::PANTS:return new Pants();default:return nullptr;}return nullptr;}virtual Mask* CreateMask(MASK_TYPE type){switch (type){case MASK_TYPE::N95_MASK:return new N95Mask();case MASK_TYPE::SURGICAL_MASK:return new SurgicalMask();default:return nullptr;}return nullptr;}
};

5、然后,就可以调用生产了

int main()
{//调用工厂生产T恤Factory* factory = new ProduceFactory();if (nullptr != factory){//生产T恤Clothe* clothe = factory->CreateClothe(CLOTHE_TYPE::T_SHIRT);if (nullptr != clothe){clothe->Show();//new的对象使用完后需要deletedelete clothe;clothe = nullptr;}//生产医用外科口罩Mask* mask = factory->CreateMask(MASK_TYPE::SURGICAL_MASK);if (nullptr != mask){mask->equip();delete mask;mask = nullptr;}}system("pause");return 0;
}

从上面的逻辑可以看出,如果工厂需要新增生产另一类产品,则必须要对抽象工厂类以及具体实现Create的工厂类进行修改,所以是不符合开闭原则的。

参考&致谢

C++ 深入浅出工厂模式(初识篇) - 知乎初识工厂模式我们先看工厂模式的介绍 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建…https://zhuanlan.zhihu.com/p/83535678

五分钟学设计模式.04.抽象工厂模式_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1y54y1B7k6?spm_id_from=0.0.header_right.history_list.click

设计模式-工厂模式 C++相关推荐

  1. Java设计模式-工厂模式(3)抽象工厂模式

    在Java设计模式-工厂模式(2)工厂方法模式 我们知道了工厂方法模式解决了简单工厂模式中的缺陷,做到了满足开闭原则,但是时代是进步的,进而又产生新的问题,工厂难道只能生产一种东西吗.我们所见到的工厂 ...

  2. Java设计模式-工厂模式(2)工厂方法模式

    在Java设计模式-工厂模式(1)简单工厂模式 中我们介绍了简单工厂模式,提到了简单工厂模式违背了开闭原则,而"工厂方法模式"是对简单工厂模式的进一步抽象化,其好处是可以使系统在不 ...

  3. Java设计模式-工厂模式(1)简单工厂模式

    Java设计模式-工厂模式(1)简单工厂模式 一.前言 1)例子 2)类图关系 3)代码实现 二.简单工厂模式 2.1.概述: 2.2.类图关系: 2.3.代码修改: 2.4.优缺点 2.5.扩展-简 ...

  4. 设计模式---工厂模式

    设计模式---工厂模式 工厂方法模式 概述:工厂方法模式中抽象工厂负责定义创建对象的接口,具体创建工作由继承抽象工厂的具体类实现. 优点:客户端不需要再负责对象的创建,从而明确了各个类的职责,如果有新 ...

  5. java设计模式工厂模式_Java中的工厂设计模式

    java设计模式工厂模式 Welcome to the Factory Design Pattern in Java tutorial. Factory Pattern is one of the C ...

  6. java设计模式工厂模式_Java中的复合设计模式

    java设计模式工厂模式 Composite pattern is one of the Structural design pattern. Composite design pattern is ...

  7. java设计模式工厂模式_Java中的桥梁设计模式

    java设计模式工厂模式 Today we will look into Bridge Design Pattern in java. When we have interface hierarchi ...

  8. java设计模式工厂模式_Java中的外观设计模式

    java设计模式工厂模式 Facade Design Pattern is one of the Structural design patterns (such as Adapter pattern ...

  9. 设计模式-工厂模式(学习)

    设计模式-工厂模式(学习) 在程序的世界里,就像射雕英雄传一样,我们的技能就像是武功一样,我们只有不断去学习练习才能有机会像郭靖一样成为"天下第一". 我认为技能和武功是很类似的, ...

  10. 设计模式-工厂模式的3中不同实现[JAVA]

    设计模式-工厂模式的3中不同实现[JAVA] 工厂模式简介 In Factory pattern, we create object without exposing the creation log ...

最新文章

  1. 暴力枚举 UVA 725 Division
  2. linux进程--fork详解(三)
  3. android int与String的转换
  4. discuz x2.5 广告位开发学习(第二步:制作)
  5. 滑动加载怎么做 php,vue之UI框架如何实现滑动加载数据
  6. linux tee命令_Linux tee命令示例
  7. 抽象类实现接口,子类继承抽象类,这三个之间的关系?
  8. vs2013制作滚屏软件
  9. 在低版本浏览器内核中适配replaceAll
  10. 【译】雄迈摄像头爆出Mirai僵尸网络
  11. 读书笔记:《从生活常识的角度看懂财务报表》
  12. 分号与逗号的区别及举例_顿号与逗号与分号间的区别是什么?
  13. html怎么设置内存当缓存,前端浏览器缓存怎么使用
  14. 《基于 DirectX11 的 3D 图形程序设计案例教程》学习一 HelloWorld
  15. 使用kali破解win7密码
  16. php面试题大全及答案
  17. 手机计算机表白公式,表白公式数学公式
  18. 薛兆丰经济学思维研究:权利在真实生活中的硬度
  19. 【MATLAB】矩阵元素及其基本运算
  20. 怎么权衡不同类型项目的收益产出比 ROI?

热门文章

  1. IT咨询服务-客户案例(四):根据图片等素材,动态生成个性化图片
  2. python解压zip文件
  3. Win10 .Net Framework 3.5 安装错误 0x800F0954
  4. 30岁女生跟20岁女生最大的区别是,20岁的女生还相信爱情
  5. qtabwidget tab样式
  6. 探花交友_第3章_今日佳人功能实现
  7. 【Python】安装crypto库(直接安装pycrypto)
  8. 表空间main恢复后报脱机状态[-3408]
  9. 屏幕适配 AndroidAutoSize 完全解析,踩坑测试 与 使用注意事项总结
  10. 获得天气相关接口三-查询当天天气