参考文献
- [1] 深入浅出工程模式(初始篇)
- [2] 三种工厂模式的C++实现
1. 什么是工厂模式
工厂模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
2. 简单工程模式
具体情形:有一个肥皂厂,生产各种肥皂,有舒肤佳,夏士莲,娜爱斯等。给这个肥皂厂建模。
UML图如下:
对于简单设计模式的结构图,我们可以很清晰的看到它的组成:
- 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。
- 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
- 具体产品角色:工厂类所创建的对象就是此角色的实例。
简单设计模式存在的目的很简单:定义一个用于创建对象的接口。
缺点:对修改不封闭,新增加产品您要修改工厂。违法了鼎鼎大名的开闭法则(OCP)。
#include <iostream>
using namespace std;
enum PRODUCTTYPE {SFJ,XSL,NAS};
// 肥皂抽象产品类
class soapBase
{
public:
virtual ~soapBase(){};
virtual void show() = 0;
};
// 具体产品类
class SFJSoap:public soapBase
{
public:
void show() {cout<<"SFJ Soap!"<<endl;}
};
class XSLSoap:public soapBase
{
public:
void show() {cout<<"XSL Soap!"<<endl;}
};
class NASSoap:public soapBase
{
public:
void show() {cout<<"NAS Soap!"<<endl;}
};
// 工厂类
class Factory
{
public:
soapBase * creatSoap(PRODUCTTYPE type)
{
switch(type)
{
case SFJ:
return new SFJSoap();
break;
case XSL:
return new XSLSoap();
break;
case NAS:
return new NASSoap();
break;
default:break;
}
}
};
// 主函数的实现
int main()
{
Factory factory;
soapBase* pSoap1 = factory.creatSoap(SFJ);
pSoap1->show();
soapBase* pSoap2 = factory.creatSoap(XSL);
pSoap2->show();
soapBase* pSoap3 = factory.creatSoap(NAS);
pSoap3->show();
delete pSoap1;
delete pSoap2;
delete pSoap3;
return 0;
}
3. 工厂方法模式
具体情形:最近莫名肥皂需求激增。于是要独立每个生产线,每个生产线只生产一种肥皂。
UML图如下:
这才是真正的工厂模式。我们能很容易看出工厂方法模式和简单工厂模式的区别之处。工厂方法模式的应用并不是只是为了封装对象的创建,而是要把对象的创建放到子类中实现:Factory中只是提供了对象创建的接口,其实现将放在Factory的子类ConcreteFactory中进行。
对于工厂方法模式的组成:
- 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。
- 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
- 抽象产品角色:它是具体产品继承的父类或者是实现的接口。
- 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。
缺点:每增加一种产品,就需要增加一个对象的工厂。如果这家公司发展迅速,推出了很多新的处理器核,那么就要开设相应的新工厂。在C++实现中,就是要定义一个个的工厂类。显然,相比简单工厂模式,工厂方法模式需要更多的类定义。
代码实现
#include<iostream>
using namespace std;
// 抽象具体产品类
class SoapBase{
public:
virtual ~SoapBase(){}
virtual void show() = 0;
};
// 具体产品类
class SFJSoap : public SoapBase{
public:
void show(){cout << "SFJ Soap" << endl;}
};
class JJSSoap : public SoapBase{
public:
void show(){cout << "JJS Soap" << endl;}
};
// 抽象工程类
class FactoryBase{
public:
virtual SoapBase* creatSoap() = 0;
};
// 具体工厂类
class SFJFactory : public FactoryBase{
public:
SoapBase* creatSoap(){
return new SFJSoap();
}
};
// 具体工厂类
class JJSFactory : public FactoryBase{
public:
SoapBase* creatSoap(){
return new JJSSoap();
}
};
// 主函数
int main(){
SFJFactory factory1;
SoapBase* sfjSoap = factory1.creatSoap();
sfjSoap->show();
JJSFactory factory2;
SoapBase* jjsSoap = factory2.creatSoap();
jjsSoap->show();
return 0;
}
4. 抽象工厂模式
具体情形:这个肥皂厂发现搞牙膏也很赚钱,决定做牙膏。牙膏有高档低档,肥皂也是。现在搞两个厂房,一个生产低档的牙膏和肥皂,一个生产高档的牙膏和肥皂。
比如,厂房一生产中华牙膏、娜爱斯肥皂,厂房二生产黑人牙膏和舒肤佳肥皂
对于上面的结构图,可以看出抽象工厂模式,比前两者更为的复杂和一般性,抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。
抽象工厂模式:给客户端提供一个接口,可以创建多个产品族中的产品对象 ,而且使用抽象工厂模式还要满足一下条件:
- 系统中有多个产品族,而系统一次只可能消费其中一族产品。
- 同属于同一个产品族的产品以其使用。
抽象工厂模式的组成(和工厂方法模式一样):
- 抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。
- 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
- 抽象产品角色:它是具体产品继承的父类或者是实现的接口。
- 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。
#include<iostream>
using namespace std;
enum SOAPTYPE{SFJ,XSL,NAS};
enum TOOTHTYPE{HR,ZH};
// 抽象产品类
class SoapBase
{
public:
virtual ~SoapBase(){}
virtual void show() = 0;
};
// 具体产品类
class SFJSoap : public SoapBase
{
public:
void show(){cout << "SFJ Soap" << endl;}
};
// 具体产品类
class NASSoap : public SoapBase
{
public:
void show(){cout << "NAS Soap" << endl;}
};
// 抽象牙膏类
class ToothBase
{
public:
virtual ~ToothBase(){};
virtual void show() = 0;
};
class HRTooth:public ToothBase
{
public:
void show() {cout<<"Hei ren Toothpaste!"<<endl;}
};
class ChinaTooth:public ToothBase
{
public:
void show() {cout<<"China Toothpaste!"<<endl;}
};
// 抽象工厂类
class FactoryBase
{
public:
virtual SoapBase* createSoap() = 0;
virtual ToothBase* createToothpaste() = 0;
};
// 具体A工厂类,生产SFJ和HR
class FactoryA : public FactoryBase
{
public:
SoapBase* createSoap(){
return new SFJSoap();
}
ToothBase* createToothpaste(){
return new HRTooth();
}
};
// 具体B工厂类,生产NAS和Chia
class FactoryB : public FactoryBase
{
public:
SoapBase* createSoap(){
return new NASSoap();
}
ToothBase* createToothpaste(){
return new ChinaTooth();
}
};
int main(){
FactoryA Factory1;
FactoryB Factory2;
SoapBase *pSoap1 = nullptr;
ToothBase *pToothpaste1 = nullptr;
pSoap1 = Factory1.createSoap();
pToothpaste1 = Factory1.createToothpaste();
pSoap1->show();
pToothpaste1->show();
SoapBase *pSoap2 = NULL;
ToothBase *pToothpaste2 = NULL;
pSoap2 = Factory2.createSoap();
pToothpaste2 = Factory2.createToothpaste();
pSoap2->show();
pToothpaste2->show();
delete pSoap1;
delete pSoap2;
delete pToothpaste1;
delete pToothpaste2;
return 0;
}