C++设计模式——简单工厂模式

来源:互联网 发布:进出口贸易数据期刊 编辑:程序博客网 时间:2024/06/06 01:49

C++设计模式——简单工厂模式

问题描述

之前在公司做了一个windows 8平台的阅读器。首先,需要将电子书中的内容渲染到屏幕上,而电子书每一页都包含各种各样的内容,比如:图形、图像和文字等等;不同的内容,就是不同的对象;在将不同的内容渲染到屏幕上之前,就需要new操作,建立不同的对象,然后再在屏幕上进行描绘。这个时候,就需要进行很多new操作,new操作分布在代码的不同地方,管理起来很麻烦,而且也很乱,到后期扩展和维护的时候,有的时候,对象多的让开发人员不知道这个对象是干什么的,这就增加了难度;同时,new操作,都会有对应的异常处理,最后,就会发现,在代码中,new了一个对象,然后,就跟着一段异常处理代码,这时编码变的极其混乱和臃肿。那么怎么办?怎么办?此时,我们需要一个新的类,专门从事对象的建立和释放,之后,对象的各种操作,和这个类没有任何关系。这个专门建立对象的类,向外暴漏创建对象的接口,供外部调用。

工厂模式有一种非常形象的描述,建立对象的类就如一个工厂,而需要被建立的对象就是一个个产品;在工厂中加工产品,使用产品的人,不用在乎产品是如何生产出来的。从软件开发的角度来说,这样就有效的降低了模块之间的耦合。

UML类图

对于工厂模式,具体上可以分为三类:

  1. 简单工厂模式;
  2. 工厂方法模式;
  3. 抽象工厂模式。

对于上面的三种工厂模式,从上到下逐步抽象,并且更具一般性。而这篇博文主要讲的是简单工厂模式,后两种会在之后的博文中接着总结。
Simply Factory DesignProductA、ProductB和ProductC继承自Product虚拟类,Show方法是不同产品的自描述;Factory依赖于ProductA、ProductB和ProductC,Factory根据不同的条件创建不同的Product对象。

适用场合

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

代码实现

/*** FileName     : SimpleFactoryPatternDemo** Author       : Jelly Young** Date         : 2013/11/17** Description  : More information, please go to http://www.jellythink.com*/#include <iostream>#include <vector>using namespace std;typedef enum ProductTypeTag{TypeA,TypeB,TypeC}PRODUCTTYPE;// Here is the product classclass Product{public:virtual void Show() = 0;};class ProductA : public Product{public:void Show(){cout<<"I'm ProductA"<<endl;}};class ProductB : public Product{public:void Show(){cout<<"I'm ProductB"<<endl;}};class ProductC : public Product{public:void Show(){cout<<"I'm ProductC"<<endl;}};// Here is the Factory classclass Factory{public:Product* CreateProduct(PRODUCTTYPE type){switch (type){case TypeA:return new ProductA();case TypeB:return new ProductB();case TypeC:return new ProductC();default:return NULL;}}};int main(int argc, char *argv[]){// First, create a factory objectFactory *ProductFactory = new Factory();Product *productObjA = ProductFactory->CreateProduct(TypeA);if (productObjA != NULL)productObjA->Show();Product *productObjB = ProductFactory->CreateProduct(TypeB);if (productObjB != NULL)productObjB->Show();Product *productObjC = ProductFactory->CreateProduct(TypeC);if (productObjC != NULL)productObjC->Show();delete ProductFactory;ProductFactory = NULL;delete productObjA;productObjA = NULL;delete productObjB;productObjB = NULL;        delete productObjC;productObjC = NULL;return 0;}

问题描述

之前讲到了C++设计模式——简单工厂模式,由于简单工厂模式的局限性,比如:工厂现在能生产ProductA、ProductB和ProductC三种产品了,此时,需要增加生产ProductD产品;那么,首先是不是需要在产品枚举类型中添加新的产品类型标识,然后,修改Factory类中的switch结构代码。是的,这种对代码的修改,对原有代码的改动量较大,易产生编码上的错误(虽然很简单,如果工程大了,出错也是在所难免的!!!)。这种对代码的修改是最原始,最野蛮的修改,本质上不能称之为对代码的扩展。同时,由于对已经存在的函数进行了修改,那么以前进行过的测试,都将是无效的,所有的测试,都将需要重新进行,所有的代码都需要进行重新覆盖。这种,增加成本,不能提高效率的事情,在公司是绝对不允许的(除非昏庸的PM)。出于种种原因,简单工厂模式,在实际项目中使用的较少。那么该怎么办?怎么办呢?需要对原有代码影响降到最小,同时能对原有功能进行扩展。

UML类图

那么今天介绍的工厂方法模式,就隆重登场了。它只是对简单工厂模式的扩展,在GOF的介绍中,它们是合并在一起的,而我则是单独分开进行讲解的,就是为了区分二者的利弊,便于大家在实际项目中进行更好的把握与应用。工厂方法模式是在简单工厂模式的基础上,对“工厂”添加了一个抽象层。将工厂共同的动作抽象出来,作为抽象类,而具体的行为由子类本身去实现,让子类去决定生产什么样的产品。

果冻想 | 一个原创文章分享网站

如图,FactoryA专心负责生产ProductA,FactoryB专心负责生产ProductB,FactoryA和FactoryB之间没有关系;如果到了后期,如果需要生产ProductC时,我们则可以创建一个FactoryC工厂类,该类专心负责生产ProductC类产品。由于FactoryA、FactoryB和FactoryC之间没有关系,当加入FactoryC加入时,对FactoryA和FactoryB的工作没有产生任何影响,那么对代码进行测试时,只需要单独对FactoryC和ProductC进行单元测试,而FactoryA和FactoryB则不用进行测试,则可省去大量无趣无味的测试工作。

适用场合

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

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

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

代码实现

/*** FileName     : FactoryMethodPatternDemo** Author       : Jelly Young** Date         : 2013/11/18** Description  : More information, please go to http://www.jellythink.com*/#include <iostream>using namespace std;class Product{public:virtual void Show() = 0;};class ProductA : public Product{public:void Show(){cout<< "I'm ProductA"<<endl;}};class ProductB : public Product{public:void Show(){cout<< "I'm ProductB"<<endl;}};class Factory{public:virtual Product *CreateProduct() = 0;};class FactoryA : public Factory{public:Product *CreateProduct(){return new ProductA ();}};class FactoryB : public Factory{public:Product *CreateProduct(){return new ProductB ();}};int main(int argc , char *argv []){Factory *factoryA = new FactoryA ();Product *productA = factoryA->CreateProduct();productA->Show();Factory *factoryB = new FactoryB ();Product *productB = factoryB->CreateProduct();productB->Show();if (factoryA != NULL){delete factoryA;factoryA = NULL;}if (productA != NULL){delete productA;productA = NULL;}if (factoryB != NULL){delete factoryB;factoryB = NULL;}if (productB != NULL){delete productB;productB = NULL;}return 0;}

0 0