设计模式之三种工厂模式与实例详解

来源:互联网 发布:iphone4移动数据开关 编辑:程序博客网 时间:2024/05/23 02:14
这两天学习了下设计模式中的工厂模式,写个总结方便以后记忆和查看。
工厂模式包括:简单工厂模式、工厂方法模式和抽象工厂模式,其中简单工厂模式不是23种标准的设计模式 
并且简单工厂模式也没有遵循开闭原则,抽象工厂模式在每一个系列的子系列中符合开闭原则,整个系列不符合,
下面将通过实例分别来讲解三种设计模式

一 简单工厂模式

参与者:

工厂角色:
是简单工厂模式的核心,它负责实现创建所有工厂实例的内部逻辑。工厂类可以被外界直接调用,创建用户需要的产品对象
抽象产品角色:
是简单工厂模式所有创建对象的父类,它负责描述所有实例所共有的公共接口
具体产品角色:
是简单工厂模式的创建目标。所有创建的对象都是充当这个角色的某个具体类的实例

适用性:

工厂类负责创建的对象比较少时

客户只关心传入工厂类的参数,对于如何创建对象(逻辑)不关心

实例:

#include "stdafx.h"#include <iostream>#include <assert.h>using namespace std;//抽象产品角色class CFruit {public:virtual void sayName() = 0;};//具体产品角色 芒果类class CMango : public CFruit{public:virtual void sayName(){cout << "I am a Mango" << endl;}};//具体产品角色 苹果类class CApple : public CFruit{public:virtual void sayName(){cout << "I am a Apple" << endl;}};//工厂角色class CFactory{public:CFruit* create(const char const * p){if (strcmp(p, "mango") == 0){return new CMango();}else if (strcmp(p, "apple") == 0){return new CApple();}else{return NULL;}}};int main(int argc, char* argv[]){printf("start!!\n");system("pause");CFactory* factory = new CFactory();CFruit* pMango = factory->create("mango");assert(pMango != NULL);pMango->sayName();system("pause");CFruit* pApple= factory->create("apple");assert(pApple != NULL);pApple->sayName();system("pause");delete factory;factory = NULL;delete pMango;pMango = NULL;delete pApple;pApple = NULL;return 0;}

补充:

在简单工厂模式中,如果我们需要重新增加一种水果,比如香蕉,那么我们不仅仅需要增加一个CBanana类,
还需要在工厂类中增加创建的条件。

二 工厂方法模式

参与者:

抽象工厂角色:
负责描述所有工厂的公共接口
具体工厂角色:
重定义工厂方法,返回一个具体产品的实例
抽象产品角色:
所有具体产品创建对象的父类,它负责描述所有实例所共有的公共接口
具体产品角色:
是简单工厂模式的创建目标。所有创建的对象都是充当这个角色的某个具体类的实例

适用性:

当一个类不知道它锁不许创建的对象的类的时候
当一个类希望由它的子类来指定它所创建的对象的时候

实例:

//抽象产品角色class CFruit {public:virtual void sayName() = 0;};//具体产品角色 芒果类class CMango : public CFruit{public:virtual void sayName(){cout << "I am a Mango" << endl;}};//具体产品角色 苹果类class CApple : public CFruit{public:virtual void sayName(){cout << "I am a Apple" << endl;}};//抽象工厂角色class CFactory{public:virtual CFruit* create() = 0;};//具体工厂角色 芒果工厂类class CMangoFactory : public CFactory{public:CFruit* create(){return new CMango();}};//具体工厂角色 苹果工厂类class CAppleFactory : public CFactory{public:CFruit* create(){return new CApple();}};int main(int argc, char* argv[]){printf("start!!\n");system("pause");CMangoFactory* pMangoFac = new CMangoFactory();CFruit* pMango = pMangoFac->create();pMango->sayName();system("pause");CAppleFactory* pAppleFac = new CAppleFactory();CFruit* pApple = pAppleFac->create();pApple->sayName();system("pause");delete pMangoFac;pMangoFac = NULL;delete pMango;pMango = NULL;delete pAppleFac;pAppleFac = NULL;delete pApple;pApple = NULL;return 0;}

补充:

当抽象方法模式中需要新增一种水果类型,如香蕉时,只需要新增一个香蕉类,一个香蕉工厂即可,并不会影响其原有代码。因此其遵循开闭原则。

三 抽象工厂模式

参与者:

抽象工厂角色:
负责描述所有工厂的公共接口
具体工厂角色:
重定义工厂方法,返回一个具体产品的实例
抽象产品角色:
所有具体产品创建对象的父类,它负责描述所有实例所共有的公共接口
具体产品角色:
是简单工厂模式的创建目标。所有创建的对象都是充当这个角色的某个具体类的实例
客户:
仅仅使用由抽象工厂和抽象产品类声明的方法

适用性:

一个系统要独立于它的产品的创建、组合和表示时
一个系统要由多个产品系列中的一个来配置时
当你要强调一系列相关的产品对象的设计以便进行联合使用时
当你提供一个产品类库,而只想显示它的接口而不是实现

实例:

//抽象产品角色class CFruit {public:virtual void sayName() = 0;};//具体产品角色 本地芒果类class CLocalMango : public CFruit{public:virtual void sayName(){cout << "I am a local Mango" << endl;}};//具体产品角色 本地苹果类class CLocalApple : public CFruit{public:virtual void sayName(){cout << "I am a local Apple" << endl;}};//具体产品角色 外地芒果类class CFieldMango : public CFruit{public:virtual void sayName(){cout << "I am a Field Mango" << endl;}};//具体产品角色 外地苹果类class CFieldApple : public CFruit{public:virtual void sayName(){cout << "I am a Field Apple" << endl;}};//抽象工厂角色class CFactory{public:virtual CFruit* createMango() = 0; virtual CFruit* createApple() = 0;};//具体工厂角色 本地水果工厂类class CLocalFruitFactory : public CFactory{public:CFruit* createMango(){return new CLocalMango();}CFruit* createApple(){return new CLocalApple();}};//具体工厂角色 外地水果工厂类class CFieldFruitFactory : public CFactory{public:CFruit* createMango(){return new CFieldMango();}CFruit* createApple(){return new CFieldApple();}};int main(int argc, char* argv[]){printf("start !!\n");system("pause");CLocalFruitFactory* pLocalfac = new CLocalFruitFactory();CFruit* pLocalApple = pLocalfac->createApple();pLocalApple->sayName();system("pause");CFruit* pLocalMango = pLocalfac->createMango();pLocalMango->sayName();system("pause");CFieldFruitFactory* pFieldfac = new CFieldFruitFactory();CFruit* pFiledApple = pFieldfac->createApple();pFiledApple->sayName();system("pause");CFruit* pFieldlMango = pFieldfac->createMango();pFieldlMango->sayName();system("pause");delete pLocalfac;pLocalfac = NULL;delete pLocalApple;pLocalApple = NULL;delete pLocalMango;pLocalMango = NULL;delete pFieldfac;pFieldfac = NULL;delete pFiledApple;pFiledApple = NULL;delete pFieldlMango;pFieldlMango = NULL;return 0;}

补充:

  当用抽象工厂新增加一个系列时,只需要创建一个产品具体类和产品系列工厂,
 这符合开闭原则,当需要增加一款产品时,则需要改动原来的代码,则不符合开闭原则,
 因此其每一个系列的子系列中符合开闭原则,整个系列不符合

总结:  

通过上面三种工厂模式可以看出,每种模式都有适用的场景,实现起来大致相同。特别是工厂方法和抽象工厂,他们侧重的点不同,一个是产品,一个是一系列的产品,并且抽象工厂也经常使用工厂方法来实现。

原创粉丝点击