一、简单工厂模式

1.1 简单工厂模式

简单工厂模式(Simple Factory Pattern)专门定义一个类来负责创建其他类的实例,被创建的实例通常具有共同的父类。

简单工厂模式,是一种实例化对象的方式,只要输入需要实例化对象的名字,就可以通过工厂对象的相应工厂函数来制造你需要的对象。

1.2 简单工厂模式的角色

(1)Factory工厂角色(工厂类):

工厂角色即工厂类,是简单工厂模式的核心,负责创建所有实例的内部逻辑,工厂类可以被外界直接调用,创建所需要的产品对象。

(2)Product(抽象产品角色):

抽象产品角色是简单工厂模式所创建的所有对象的父类,负责描述所有实例所共有的公告接口。所创建的具体产品对象都是其子类对象。

(3)ConcreteProduct(具体产品角色):

具体产品角色是简单工厂模式的创建目标。每个具体产品角色都继承了抽象产品角色,需要实现定义在抽象产品中的方法。

ProductA、ProductB和ProductC继承自Product虚拟类,Show方法是不同产品的自描述;Factory依赖于ProductA、ProductB和ProductC,Factory根据不同的条件创建不同的Product对象

依赖关系:箭头指向被依赖的一方

继承关系:

1.3 简单工厂模式的应用

在程序中,需要创建的对象很多,导致对象的new操作多且杂时,需要使用简单工厂模式;
由于对象的创建过程是我们不需要去关心的,而我们注重的是对象的实际操作,所以,我们需要分离对象的创建和操作两部分,如此,方便后期的程序扩展和维护。

1.4 简单工厂模式的优缺点

优点:

本着高内聚低耦合的原则,将系统的逻辑部分和功能分开。

缺点:

  • 简单工厂模式会增加系统类的个数,在一定程度上增加了系统的复杂度和理解难度;
  • 系统扩展难,一旦增加新产品,就需要修改工厂逻辑,不利于系统的扩展与维护;简单工厂模式中所有产品的创建都是由同一个工厂创建,工厂类职责较重,业务逻辑较为复杂,具体产品与工厂类之间耦合度高,严重影响了系统的灵活性和扩展性

1.5 简单工厂模式实现

某电视机厂为各个品牌代工生产电视机,可以使用简单工厂的模式来实现。

#include <iostream>
#include <vector>
using namespace std;typedef enum ProductTypeTag
{Hair,Hisense,
}PRODUCTTYPE;//抽象产品类 TV(电视机类)
class TV
{
public:virtual void Show() = 0;virtual ~TV(){};//声明析构函数为虚函数,防止内存泄漏
};//具体产品类 HairTV(海尔电视类)
class HairTV : public TV
{
public:void Show(){cout<<"I'm HairTV "<<endl;}
};//具体产品类 HisenseTV(海信电视类)
class  HisenseTV : public TV
{
public:void Show(){cout<<"I'm HisenseTV"<<endl;}
};// 工厂类 TVFactory(电视机工厂类)
class TVFactory
{
public:TV* CreateTV(PRODUCTTYPE type){switch (type){case Hair:return new HairTV();case Hisense:return new HisenseTV();default:return NULL;}}
};int main(int argc, char *argv[])
{// 创建工厂类对象TVFactory* myTVFactory = new  TVFactory();TV* hairTV = myTVFactory->CreateTV(Hair);if (hairTV != NULL)hairTV->Show();TV* hisenseTV = myTVFactory->CreateTV(Hisense);if (hisenseTV != NULL)hisenseTV->Show();delete  myTVFactory;myTVFactory = NULL;delete hairTV;hairTV = NULL;delete hisenseTV;hisenseTV = NULL;  return 0;
}

调试结果:

TVFactory 是工厂类,它是整个系统的核心,提供了静态工厂方法CreateTV(),该方法中包含一个字符串类型的参数,在内部业务逻辑中根据参数值得不同实例化不同的具体产品类,返回相依的对象。简单工厂模式的缺点是 如增加 生成TCL电视时,需要修改工厂类TVFactory。

小结:

在程序中,需要创建的对象很多,导致对象的new操作多且杂时,需要使用简单工厂模式。

二、工厂方法模式

2.1 工厂方法简介

简单工厂模式中最大的缺点是当有新产品要加入系统时,必须要修改工厂类,加入必要的处理逻辑,违背了“开闭原则”

工厂方法模式定义:在工厂模式中,工厂父类负责定义创建产品对象的公告接口,而工厂子类负责生成具体的产品对象。目的是将产品的实例化操作延迟到工厂子类中完成,通过工厂子类来确定究竟应该实例化哪一个具体产品类。

2.2 模式结构

(1)Product (抽象产品)

抽象产品是定义产品的接口,是工厂方法模式所创建对象的超类型,也是产品对象的共同父类或接口。

(2)ConcreteProduct(具体产品)

具体产品实现了抽象产品的接口,某种类型的具体产品由专门的具体工厂创建。

(3)Factory(抽象工厂)

(4)ConcreteFactory(具体工厂)

具体工厂是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户调用,返回一个具体产品类的实例。

2.3 应用

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

1.在设计的初期,就考虑到产品在后期会进行扩展的情况下,可以使用工厂方法模式;

2.产品结构较复杂的情况下,可以使用工厂方法模式;

2.4 优缺点

优点:系统的扩展性好,符合“开闭原则”  。系统加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品即可。

缺点:在添加新产品时,需要编写新的具体产品类,而且要提供与之对应的具体工厂类,系统中类的个数将成对增加,一定程度上增加了系统的复杂度。

2.5 举例

简单工厂模式,通过一个电视机代工厂来生产电视机,当需要增加新的品牌的电视机时不得不修该工厂类中的工厂方法,违反了“开闭原则”。

工厂方法模式,将原有的工厂进行分割,为每种品牌的电视机提供一个子工厂,海尔工厂专门负责生产海尔电视机,海信工厂专门负责生产海信电视机,若增加TCL电视,只需要增加一个新的TCL工厂。

#include <iostream>
using namespace std;/*抽象产品类 TV(电视机类)*/
class TV
{
public:virtual void Show() = 0;virtual ~TV();//声明析构函数为虚函数,防止内存泄漏
};/*具体产品类 HairTV(海尔电视机类)*/
class HairTV : public TV
{
public:void Show(){cout<< "I'm HairTV"<<endl;}
};
/*具体产品类 HisenseTV(海信电视机类)*/
class HisenseTV : public TV
{
public:void Show(){cout<< "I'm HisenseTV"<<endl;}
};
/*工厂类(电视机工厂类)*/
class TVFactory
{
public:virtual TV *CreateTV() = 0;virtual ~TVFactory(){};//析构函数声明为虚函数,防止内存泄漏
};/*具体工厂类 HairTVFactory(海尔电视机工厂类)*/
class HairTVFactory : public TVFactory
{
public:TV *CreateTV(){return new HairTV ();}
};/*具体工厂类 HisenseTV(海信电视机工厂类)*/
class HisenseTVFactory : public TVFactory
{
public:TV *CreateTV(){return new HisenseTV ();}
};int main(int argc , char *argv [])
{TVFactory *hairTVFactory = new HairTVFactory();TV *hairTV = hairTVFactory->CreateTV();hairTV->Show();TVFactory *hisenseTVFactory = new HisenseTVFactory();TV *hisenseTV = hisenseTVFactory->CreateTV();hisenseTV->Show();if (hairTVFactory!= NULL){delete hairTVFactory;hairTVFactory = NULL;}if (hairTV != NULL){delete hairTV;hairTV = NULL;}if (hisenseTVFactory != NULL){delete hisenseTVFactory;hisenseTVFactory = NULL;}if (hisenseTV != NULL){delete hisenseTV;hisenseTV = NULL;}return 0;
}

运行结果:

三、抽象工厂模式

3.1 抽象工厂模式

抽象工厂模式是工厂方法模式的泛化版,工厂模式是一种特殊的抽象工厂模式,在工厂模式中,每个具体工厂只能生产一种具体的产品,如海尔电视机厂只生产海尔电视机,而抽象工厂方法模式中,一个具体的工厂可以生产多个具体产品。

3.2 模式角色

产品等级结构与产品族:

产品等级结构:

(1)AbstractFactory(抽象工厂)

抽象工厂用于声明生成抽象产品的方法,在一个抽象工厂中可以定义一组方法,每一个方法对应一个产品等级结构。

(2)ConcreteFactory  (具体工厂)

具体工厂实现了抽象工厂声明的抽象产品的方法,生成一组具体产品

(3)AbstractProduct (抽象产品)

抽象产品为每种产品声明接口,在抽象产品中定义了产品的抽象业务方法。

(4)ConcreteProdunct (具体产品)

具体产品定义具体工厂生产的具体产品对象,实现抽象产品接口中定义的业务方法。

3.3 应用

当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。

  1. 适合于产品之间相互关联、相互依赖且相互约束的地方
  2. 需要动态切换产品族的地方

3.4 优缺点

优点:

  1. 抽象工厂模式将产品族的依赖与约束关系放到抽象工厂中,便于管理。
  2. 职责解耦,用户不需要关心一堆自己不关心的细节,由抽象工厂来负责组件的创建
  3. 切换产品族容易,只需要增加一个具体工厂实现,客户端选择另一个套餐就可以了

缺点:

  1. 抽象工厂模式类增加的速度很快,有一个产品族就需要增加一个具体工厂实现,比较繁琐
  2. 产品族难以扩展产品。当产品族中增加一个产品时,抽象工厂接口中需要增加一个函数,对应的所有具体工厂实现都需要修改,修改放大严重。
  3. 抽象工厂并未完全屏蔽创建细节,给出的都是组件。对于这种情况可以结合工厂模式或简单工厂模式一起使用。

3.5 举例

如一个电器工厂可以生产多种类型的电器,如海尔工厂可以生产海尔电视机、海尔空调等,TCL工厂可以生产TCL电视、TCL空调等。相同品牌的电器构成一个产品族,而相同类型的电器构成了一个产品等级结构。

#include <iostream>
using namespace std;// 抽象产品类类 Television(电视机类)
class Television
{
public:virtual void Show() = 0;virtual ~Television(){};//析构函数声明为虚函数,防止内存泄漏
};//具体产品类 HaierTelevision(海尔电视机类)
class HaierTelevision : public Television
{
public:void Show(){cout << "I'm HaierTelevision" << endl;}
};
//具体产品类 TCLTelevision(TCL电视机类)
class TCLTelevision : public Television
{
public:void Show(){cout << "I'm TCLTelevision" << endl;}
};// 抽象产品类  AirCondition(空调类)
class AirCondition
{
public:virtual void Show() = 0;virtual ~AirCondition(){};//析构函数声明为虚函数,防止内存泄漏
};
//具体产品类 HairAirCondition(海尔空调类)
class HairAirCondition : public AirCondition
{
public:void Show(){cout << "I'm HairAirCondition" << endl;}
};
//具体产品类 TCLAirCondition(TCL空调类)
class TCLAirCondition : public AirCondition
{
public:void Show(){cout << "I'm TCLAirCondition" << endl;}
};// 抽象工厂类 EFactory(电器工厂类)
class EFactory
{
public:virtual Television* CreateTelevision() = 0;virtual AirCondition* CreateAirCondition() = 0;virtual ~EFactory(){};//析构函数声明为虚函数,防止内存泄漏
};
//具体工厂类 HairFactory(海尔工厂类)
class HairFactory : public EFactory
{
public:Television* CreateTelevision(){return new HaierTelevision();}AirCondition* CreateAirCondition(){return new HairAirCondition();}
};
//具体工厂类 TCLFactory(TCL工厂类)
class TCLFactory : public EFactory
{
public:Television* CreateTelevision(){return new TCLTelevision();}AirCondition* CreateAirCondition(){return new TCLAirCondition();}
};int main(int argc, char *argv[])
{EFactory *hairFactory = new HairFactory ();/*实例化工厂抽象类*/Television *haierTelevision =hairFactory->CreateTelevision();/*实例化产品抽象类*/AirCondition *haierAirCondition = hairFactory->CreateAirCondition();haierTelevision->Show();haierAirCondition->Show();EFactory *tCLFactory = new TCLFactory ();Television *tCLTelevision = tCLFactory->CreateTelevision();AirCondition *tCLAirCondition = tCLFactory->CreateAirCondition();tCLTelevision->Show();tCLAirCondition->Show();if (hairFactory != NULL){delete hairFactory;hairFactory = NULL;}if (haierTelevision != NULL){delete haierTelevision;haierTelevision= NULL;}if (tCLAirCondition != NULL){delete tCLAirCondition;tCLAirCondition = NULL;}if (tCLFactory != NULL){delete tCLFactory;tCLFactory= NULL;}if (tCLTelevision != NULL){delete tCLTelevision;tCLTelevision = NULL;}if (tCLAirCondition != NULL){delete tCLAirCondition;tCLAirCondition = NULL;}
}

运行结果:

四、总结

  1. 大家应该已经发现了,其实抽象工厂模式如果只有一个组件的话,其实是退化到了工厂方法模式,也就是没有了产品族的概念,只剩一个产品了,因此简单工厂,工厂方法,抽象工厂这三者之间是有内在联系的,区别只是产品的复杂度。
  2. 抽象工厂的本质是选择产品族,因此大家可以根据这个特征来识别是否可以应用抽象工厂。

简单工厂:唯一工厂类,一个产品抽象类,工厂类的创建方法依据入参判断并创建具体产品对象。
工厂方法:多个工厂类,一个产品抽象类,利用多态创建不同的产品对象,避免了大量的if-else判断。
抽象工厂:多个工厂类,多个产品抽象类,产品子类分组,同一个工厂实现类创建同组中的不同产品,减少了工厂子类的数量。

参考文献:

【1】工厂模式(C++实现):工厂模式(C++实现) - 1点er执着 - 博客园

【2】设计模式之简单工厂,工厂方法模式(c++):设计模式之简单工厂,工厂方法模式(c++)_u012219045的专栏-CSDN博客_c++ 工厂方法模式

【3】C++实现设计模式之 — 简单工厂模式:C++实现设计模式之 — 简单工厂模式 - jostree - 博客园

【4】 C++设计模式之简单工厂模式实例:https://www.jb51.net/article/55858.htm

【5】C++设计模式之工厂方法模式:https://www.jb51.net/article/55860.htm

【6】C++设计模式之抽象工厂模式:https://www.jb51.net/article/55861.htm

【7】抽象工厂模式和工厂模式的区别: 抽象工厂模式和工厂模式的区别? - 知乎

【8】抽象工厂模式应用场景(24种设计模式优缺点):https://www.haitaoseo.com/960718.html

C++创建型模式-工厂模式相关推荐

  1. JavaScript 设计模式核⼼原理与应⽤实践 之 创建型:工厂模式·简单工厂——区分“变与不变”

    JavaScript 设计模式核⼼原理与应⽤实践 之 创建型:工厂模式·简单工厂--区分"变与不变" 先来说说构造器 在介绍工厂模式之前,为了辅助大家的理解,我想先在这儿给大家介绍 ...

  2. JavaScript 设计模式核⼼原理与应⽤实践 之 创建型:工厂模式·抽象工厂——理解“开放封闭”

    JavaScript 设计模式核⼼原理与应⽤实践 之 创建型:工厂模式·抽象工厂--理解"开放封闭" 一个不简单的简单工厂引发的命案 在实际的业务中,我们往往面对的复杂度并非数个类 ...

  3. 设计模式(20):创建型-抽象工厂模式(Abstract Factory)

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...

  4. 【创建型】工厂模式(Factory Pattern)详解

    工厂模式分为简单工厂.工厂方法.抽象工厂模式. 这一篇说一下简单工厂.工厂方法: 简单工厂 :用来生产同一等级结构中的任意产品.(不支持拓展增加产品) 工厂方法 :用来生产同一等级结构中的固定产品.( ...

  5. (创建型)设计模式——工厂模式(factory)

    ps:在以下讲述工厂模式中,模仿的场景如下:我们需要生产Car,建立相对应的CarFactory.使用CarFactory工厂来生产Car,并且可以在生产过程中进行一些处理.类图和代码如下. 1.Mo ...

  6. Java设计模式之创建型:原型模式

    一.什么是原型模式: 原型模式主要用于对象的创建,使用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象.UML类图如下: 原型模式的核心是就是原型类 Prototype,Prototype ...

  7. Java设计模式之创建型:建造者模式

    一.什么是建造者模式: 建造者模式将复杂产品的创建步骤分解在在不同的方法中,使得创建过程更加清晰,从而更精确控制复杂对象的产生过程:通过隔离复杂对象的构建与使用,也就是将产品的创建与产品本身分离开来, ...

  8. 创建型设计模模式---原型模式

    设计模式 序号 内容 链接地址 1 设计模式七大原则 https://blog.csdn.net/qq_39668819/article/details/115390615 2 创建型设计模式–工厂模 ...

  9. 创建型设计模模式---建造者模式

    设计模式 序号 内容 链接地址 1 设计模式七大原则 https://blog.csdn.net/qq_39668819/article/details/115390615 2 创建型设计模式–工厂模 ...

  10. 设计模式-创建型模式-工厂模式(工厂三兄弟) TypeScript

    设计模式-创建型模式-工厂模式(工厂三兄弟) TypeScript 简单工厂模式 定义一个接口,三个具体类.然后书写如下,通过选择,生产出相应的对象 // 定义Shape接口 interface Sh ...

最新文章

  1. 第十六届全国大学生智能汽车竞赛华东赛区 承办情况汇报
  2. SecureCRT错误:The client has
  3. Android Studio通过JNI调用NDK程序
  4. 关注Cortex-M处理器,M0、M3、M4简单对比
  5. 各种不同几何形状布局布阵下的GDOP相对值图
  6. (三)html5的结构
  7. 【bzoj2693】jzptab 莫比乌斯反演+线性筛
  8. 重学java基础第二十五课:数据类型
  9. 【新书速递】你想知道的通信“灵魂三问”都在这里……(福利再现)
  10. WordPress模板-ripro主题系列对接易支付通用模块插件
  11. golang-gui编程
  12. 用SpringBoot集成Netty开发一个基于WebSocket的聊天室
  13. 连接数据线截图/截视频
  14. Java常用关键字查询
  15. 【图像分类】2021-Twins NeurIPS
  16. 京东青龙面板撸豆_搭建环境流程
  17. 单元测试总结反思_考试反思,考试反思作文
  18. [1025]python地理处理包shapely
  19. 前端应该掌握的Mysql
  20. 芯片启动:从Bootrom到Linux完整启动流程

热门文章

  1. VMware ESXi克隆导出虚拟机下载时网络错误(或创建时FileNotFound)解决
  2. Foster Friess 积极成长策略
  3. java swing 聊天气泡_Java Swing中的聊天气泡
  4. SpringBoot项目启动报xxx.FeignClientSpecification问题的原因及解决办法
  5. 玻色量子荣登《麻省理工科技评论》2021“50家聪明公司”榜单
  6. 加密方式---迅雷链接加密规则
  7. Neo4j数据导入导出
  8. 【转】《信号完整性分析》个人学习笔记
  9. 各平台安装sshfs
  10. matlab中逻辑非运算,MATLAB:图像的与、或、非、异或逻辑运算(、|、~、xor)