您的位置:首页 > 其它

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

2017-09-09 00:31 429 查看
这两天学习了下设计模式中的工厂模式,写个总结方便以后记忆和查看。

工厂模式包括:简单工厂模式、工厂方法模式和抽象工厂模式,其中简单工厂模式不是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;
}

补充:

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

总结:  

通过上面三种工厂模式可以看出,每种模式都有适用的场景,实现起来大致相同。特别是工厂方法和抽象工厂,他们侧重的点不同,一个是产品,一个是一系列的产品,并且抽象工厂也经常使用工厂方法来实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息