工厂模式属于创建型模式,大致可以分为三类,简单工厂模式、工厂方法模式、抽象工厂模式。

一. 简单工厂模式

简单工厂模式,它的主要特点是需要在工厂类中做判断,从而创造相应的产品。当增加新的产品时,就需要修改工厂类。举个例子,有一家电子产品生产厂家,它只有一个工厂,能够生产两种型号的产品,A 和 B。可以想像一下,A是电吹风,B是电风扇。客户需要什么样的吹风类产品,一定要显示地告诉生产工厂。

代码实现:

  1. enum CTYPE {PRODUCT_A, PRODUCT_B};
  2. //抽象产品类
  3. class Product
  4. {
  5. public:
  6. virtual void Show() = 0;
  7. };
  8. //具体产品A
  9. class ProductA: public Product
  10. {
  11. public:
  12. void Show() { cout<<"Product A"<<endl; }
  13. };
  14. //具体产品B
  15. class ProductB: public Product
  16. {
  17. public:
  18. void Show() { cout<<"Product B"<<endl; }
  19. };
  20. //唯一的工厂,可以生产两种型号的产品,在内部判断
  21. class Factory
  22. {
  23. public:
  24. Product* CreateProduct(enum CTYPE ctype)
  25. {
  26. if(ctype == PRODUCT_A) //工厂内部判断
  27. return new ProductA(); //生产产品A
  28. else if(ctype == PRODUCT_A)
  29. return new ProductB(); //生产产品B
  30. else
  31. return NULL;
  32. }
  33. };
  34. int main()
  35. {
  36. Factory fac; //工厂
  37. Product *pro = fac.CreateProduct(PRODUCT_A);//生产产品A
  38. pro->Show();
  39. return 0;
  40. }

缺点:

由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。

打个比方:

这个工厂在刚建厂时,就要事先把以后的要生产的产品考虑好,部门划分好。如果要生产新的产品,就要改变工厂的空间布局,部门也要重新划分,这是很不利的。当然如果工厂以后发展不大,也就是创建的对象比较少时,还是可以用的。

二. 工厂方法模式

所谓工厂方法模式,是指定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。

还以刚才的例子解释,这家电子厂赚了不少钱,于是决定再开设一个厂,其中一个工厂专门用来生产A型号的产品,也就是只生产电吹风,而另一工厂专门用
来生产B型号的产品,也就是只生产电风扇,这样分工明确了。以后客户要再下定单时,可以直接找到相关的工厂了,比如要A型号的产品,就找A工厂要,不再担
心下的定单是A,生产出来的是B产品了。

代码实现:

  1. class Product
  2. {
  3. public:
  4. virtual void Show() = 0;
  5. };
  6. //产品A
  7. class ProductA: public Product
  8. {
  9. public:
  10. void Show()
  11. {
  12. cout<<"Product A"<<endl;
  13. }
  14. };
  15. //产品B
  16. class ProductB: public Product
  17. {
  18. public:
  19. void Show()
  20. {
  21. cout<<"Product B"<<endl;
  22. }
  23. };
  24. //抽象工厂
  25. class Factory
  26. {
  27. public:
  28. virtual Product* CreateProduct() = 0;
  29. };
  30. //生产A的工厂
  31. class FactoryA: public Factory
  32. {
  33. public:
  34. Product* CreateProduct()
  35. {
  36. return new ProductA;
  37. }
  38. };
  39. //生产B的工厂
  40. class FactoryB: public Factory
  41. {
  42. public:
  43. Product* CreateProduct()
  44. {
  45. return new ProductB;
  46. }
  47. };
  48. int main()
  49. {
  50. Factory* fac = new FactoryA(); //A工厂
  51. Product* p = fac->CreateProduct(); //生产产品
  52. p->Show();
  53. return 0;
  54. }

其实你会发现,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行,你想要加功能,本来是改工厂类的,而现在是修改客户端。

这有什么好处呢?举个例子,有三个客户原来要A产品,现在改卖B产品,在代码中体现为:

简单工厂的处理:

  1. Factory fac; //工厂
  2. Product *pro1 = fac.CreateProduct(PRODUCT_A);//生产产品A
  3. Product *pro2 = fac.CreateProduct(PRODUCT_A);//生产产品A
  4. Product *pro3 = fac.CreateProduct(PRODUCT_A);//生产产品A
  5. //改为B产品,这里要改三个地方
  6. //Product *pro1 = fac.CreateProduct(PRODUCT_B);//生产产品B
  7. //Product *pro2 = fac.CreateProduct(PRODUCT_B);//生产产品B
  8. //Product *pro3 = fac.CreateProduct(PRODUCT_B);//生产产品B
  9. pro1->Show();
  10. pro2->Show();
  11. pro3->Show();

工厂方法的处理:

  1. Factory* fac = new FactoryA(); //A工厂
  2. //改为B产品,这里只改一个地方
  3. //Factory* fac = new FactoryB(); //B工厂
  4. Product* pro1 = factory_A->CreateProduct(); //生产产品
  5. Product* pro2 = factory_A->CreateProduct(); //生产产品
  6. Product* pro3 = factory_A->CreateProduct(); //生产产品
  7. pro1->Show();
  8. pro2->Show();
  9. pro3->Show();

这里可以看到工厂方法的好处了吧,工厂方法模式是简单工厂模式的进一步抽象和推广,它集中封装了对象的创建,使得要更换产品时,不需要做大的改动就可以实现,降低了客户程序与产品对象的耦合。

优点:

相对于简单工厂模式来说,这样分工更加明确,当需要新产品时,就建一个新的工厂,而不是对原工厂类进行修改。这样做满足了"开放-封闭"原则,即可以扩展,不可修改。

缺点:

1. 每增加一种产品,就需要增加一个对象的工厂。在C++实现中,就是要定义一个个的工厂类。显然,相比简单工厂模式,工厂方法模式需要更多的类定义。

2. Factory 模式仅仅局限于一类类(就是说 Product 是一类,有一个共同的基类),如果我们要为不同类的类提供一个对象创建的接口,那就要用AbstractFactory了。

打个比方:

如果这家公司发展迅速,推出了很多新的产品,那么就要开设相应的新工厂,一种产品一个工厂。这对于客户来说是好事,分工明确了白;但对于工厂自己来说开销也变大了。

如要我想要生产核心芯片,但是芯片不是产品,不能继承于product类。因为产品和零部件,不是一类。

三. 抽象工厂模式

抽象工厂模式,它定义为提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

还以上面的例子解释,这家公司经营的还不错,针对其核心技术都申请了专利,后来生始生产相关电子芯片了
(像三星一样,即生产产品也生产芯片)。对于这种情况,我们不能在抽象产品类上继承一个零部件,因为产品和芯片没有什么共同之处,完全是两个领域。你要做
芯片,就要专心做,当成一个新的领域,不能用以前产品的那一套流程。这样划分才明确,才能更好的实现高内聚,低耦合的明标。

  1. //抽象产品类
  2. class Product
  3. {
  4. public:
  5. virtual void Show() = 0;
  6. };
  7. //产品A
  8. class ProductA: public Product
  9. {
  10. public:
  11. void Show()
  12. {
  13. cout<<"Product A"<<endl;
  14. }
  15. };
  16. //产品B
  17. class ProductB: public Product
  18. {
  19. public:
  20. void Show()
  21. {
  22. cout<<"Product B"<<endl;
  23. }
  24. };
  25. //抽象芯片类
  26. class Chip
  27. {
  28. public:
  29. virtual void Show() = 0;
  30. };
  31. //芯片A
  32. class ChipA: public Chip
  33. {
  34. public:
  35. void Show()
  36. {
  37. cout<<"Chip A"<<endl;
  38. }
  39. };
  40. //芯片B
  41. class ChipB: public Chip
  42. {
  43. public:
  44. void Show()
  45. {
  46. cout<<"Chip B"<<endl;
  47. }
  48. };
  49. //抽象工厂类
  50. class Factory
  51. {
  52. public:
  53. virtual Product* CreateProduct() = 0;
  54. virtual Chip* CreateChip() = 0;
  55. };
  56. //生产A的工厂
  57. class FactoryA: public Factory
  58. {
  59. public:
  60. Product* CreateProduct() //产品
  61. {
  62. return new ProductA;
  63. }
  64. Chip* CreateChip() //芯片
  65. {
  66. return new ChipA;
  67. }
  68. };
  69. //生产B的工厂
  70. class FactoryB: public Factory
  71. {
  72. public:
  73. Product* CreateProduct() //产品
  74. {
  75. return new ProductB;
  76. }
  77. Chip* CreateChip()  //芯片
  78. {
  79. return new ChipB;
  80. }
  81. };
  82. int main()
  83. {
  84. Factory* factury = new FactoryA(); //A工厂
  85. Product* product = factury->CreateProduct(); //生产产品
  86. Chip* chip = factury->CreateChip(); //生产芯片
  87. product->Show();
  88. chip->Show();
  89. return 0;
  90. }

我们可以发现,抽象工厂比工厂模式所能处理的产品更多,最关健的是这些产品有不同的基类。

优点:

1. AbstractFactory 模式关键就是将这一组对象的创建封装到一个用于创建对象的工厂类(ConcreteFactory)中,维护这样一个工厂创建类总比维护 n 多相关对象的创建过程要简单的多。

2. 它的最大好处是易于交换产品系列,比如我要B工厂的产品,只需要在客户端代码修改一处即可。

打个比方:

这时客户只要知道A工厂是生产A类的产品和芯片的,B工厂是生产B类的,其它都不用关心,只要想要与A类相关的东东就去找A就行了。

四. 总结:

1. 简单工厂模式,所有的产品都在工厂类中进行生产。功能单一时,没有什么问题,但是当增加很多新产品时,就要不断的修改产品类,易于出错,也违反了对修改是封闭的原则。

2. 工厂方法模式,每个工厂生产一种产品,这样分工更加明确。当增加新产品时,只需增加一个工厂类,而不用修改原有工厂类,这样工厂类的耦合度就降低了。

3. 抽象工厂模式,比工厂方法模式处理的情况更多。主要是对不同产品的处理,这时的工厂能够生产多种产品,这多种产品虽然没有共同基类,但是却属于一类,具体体现在都是由同一个工厂生产。

设计模式C++描述----03.工厂(Factory)模式的更多相关文章

  1. Java设计模式(二) 工厂方法模式

    本文介绍了工厂方法模式的概念,优缺点,实现方式,UML类图,并介绍了工厂方法(未)遵循的OOP原则 原创文章.同步自作者个人博客 http://www.jasongj.com/design_patte ...

  2. 设计模式-03工厂方法模式(Factory Method Pattern)

    插曲.简单工厂模式(Simple Factory Pattern) 介绍工厂方法模式之前,先来做一个铺垫,了解一下简单工厂模式,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背 ...

  3. 设计模式(2)工厂方法模式(Factory Method)

    设计模式(0)简单工厂模式 设计模式(1)单例模式(Singleton) 源码地址 0 工厂方法模式简介 0.0 工厂方法模式定义 工厂方法模式是在简单工厂模式基础上,为解决更复杂的对象创建问题而衍生 ...

  4. 设计模式(三)工厂方法模式(Factory Pattern)

    一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是——简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以 ...

  5. [设计模式3]--工厂(Factory)模式

    原文出处:http://blog.csdn.net/lwbeyond/article/details/7528309 工厂模式属于创建型模式,大致可以分为三类,简单工厂模式.工厂方法模式.抽象工厂模式 ...

  6. Head First 设计模式 —— 04. 工厂 (Factory) 模式

    思考题 如何将实例化具体类的代码从应用中抽离,或者封装起来,使它们不会干扰应用的其他部分? P111 将实例化具体类的代码放入一个对象中管理,通过不同入参决定实例化具体的类 简单工厂 不是23种GOF ...

  7. PHP设计模式(二)工厂方法模式(Factory Method For PHP)

    简单工厂简述: 简单工厂模式实现了生产产品类的代码跟客户端代码分离,在工厂类中你可以添加需要生成长跑的逻辑代码(new 产品类),但是问题来了,优秀的代码是符合"开闭原则"如果你要 ...

  8. JAVA设计模式——第 5 章 工厂方法模式【Factory Method Pattern】(转)

    女娲补天的故事大家都听说过吧,今天不说这个,说女娲创造人的故事,可不是“造人”的工作,这个词被现代人滥用了.这个故事是说,女娲在补了天后,下到凡间一看,哇塞,风景太优美了,天空是湛蓝的,水是清澈的,空 ...

  9. Java设计模式学习笔记(三) 工厂方法模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 简介 上一篇博客介绍了简单工厂模式,简单工厂模式存在一个很严重的问题: 就是当系统需要引入 ...

随机推荐

  1. Android 禁止Edittext弹出系统软键盘 的几种方法

    第一种方法:在XML文件下添加: android:focusable="true" android:focusableInTouchMode="true" 第二 ...

  2. Maven 梳理-安装配置

    项目构建过程包括[清理项目]→[编译项目]→[测试项目]→[生成测试报告]→[打包项目]→[部署项目]这几个步骤,这六个步骤就是一个项目的完整构建过程. 下载后解压   配置环境变量 F:\jtDev ...

  3. java面向对象,数据类型深入

    java程序员面试题day02 1.类和对象有什么区别? java中的类通过class关键字进行定义,代表的是一种抽象的集合,在类中可以定义各种的属性和方法,代表的是每一个类的实例的特定的数据和动作, ...

  4. linux下搭建nginx+mysql+apache

    对于开发人员来说,进行Web开发时可以用Apache进行网站测试,然而当一个Web程序进行发布时,Apache中并发性能差就显得很突出,这时配置一台Nginx服务器显得尤为重要. 以下是配置Nginx ...

  5. SpringBoot导入jsp依赖始终报错

    先粘出我自己的pom代码: <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&qu ...

  6. Mac 安装node npm cnpm vue 以及卸载 node 和 npm 的方法 清空npm缓存的方法

    S01 安装node(内含npm) 首先,到官网下载长期支持版,截止目前,最新的长期支持版本号是10.16.3 https://nodejs.org/zh-cn/download/ 下载完毕后,安装该 ...

  7. 快学Scala 第八课 (嵌套类)

    嵌套类: class Human { class Student{ val age = 10 } } object ClassDemo { def main(args: Array[String]): ...

  8. Android 调用 WebService

    1.WebService简介 PS:如果看完上面简介还不是很清楚的话,那么就算了,之前公司就用C#搭的一个WebService! 本节我们并不讨论如何去搭建一个WebService,我们仅仅知道如何去 ...

  9. 六、springboot 简单优雅是实现短信服务

    前言 上一篇讲了 springboot 集成邮件服务,接下来让我们一起学习下springboot项目中怎么使用短信服务吧. 项目中的短信服务基本上上都会用到,简单的注册验证码,消息通知等等都会用到.所 ...

  10. mybatis的环境搭建以及问题

    1.mybatis中3个重要的类或者接口 1)SqlSessionFactoryBuilder类 用它来创建工厂对象,它重载了9次build()方法,我们常用build(inputstream)来创建 ...