一 简单工厂模式
假设现在需要创建很多类型的对象,程序中各个地方大量的使用new会给程序管理带来很大的麻烦,简单工厂模式就是通过创建一个工厂类,用这个工厂类来生产各种不同类型的产品。在工厂类中根据需要的产品类型,进行生产产品,所以事先需要将创建产品的代码放入工厂类中。
#include<iostream>
using namespace std;
enum ProductType{
TypeA,
TypeB,
TypeC
};
class Product{
public:
virtual void showType()=0;
virtual ~Product(){}
};
class ProductA:public Product{
public:
void showType(){
cout<<"I am ProductA"<<endl;
}
virtual ~ProductA(){}
};
class ProductB:public Product{
public:
void showType(){
cout<<"I am ProductB"<<endl;
}
virtual ~ProductB(){}
};
class ProductC:public Product{
public:
void showType(){
cout<<"I am ProductC"<<endl;
}
virtual ~ProductC(){}
};
class Factory{
public:
Product* creatProduct(ProductType aType){
switch(aType){
case TypeA:
return new ProductA();
case TypeB:
return new ProductB();
case TypeC:
return new ProductC();
default:
return NULL;
}
}
};
int main(){
Factory* aFactory=new Factory();
Product* aProductA=aFactory->creatProduct(TypeA);
if(aProductA!=NULL) aProductA->showType();
Product* aProductB=aFactory->creatProduct(TypeB);
if(aProductB!=NULL) aProductB->showType();
Product* aProductC=aFactory->creatProduct(TypeC);
if(aProductC!=NULL) aProductC->showType();
delete aProductA;
aProductA=NULL;
delete aProductB;
aProductB=NULL;
delete aProductC;
aProductC=NULL;
return 0;
}
工厂类中用了一个switch语句根据产品类型进行生产。然而我们并不知道需要多少类型的产品,当我们需要生产目前类型中没有的产品,比如ProductD,就需要在工厂类中增加新的case语句进行生产。这种修改违反了开放封闭原则:应该进行代码扩展,而不是修改代码。当进行软件测试时就需要重新测试修改过的代码了。
二 工厂方法模式
简单工厂模式的缺点是修改了代码,而不是扩展代码。为此引入工厂方法模式,由一个抽象工厂派生出工厂A、B,让专门的工厂A生产产品A,工厂B生产产品B,当需要一个新类型的产品C时,可以在原来的基础上增加一个新的工厂C,然后生产产品C。这样进行软件测试的时候就没必要测试之前写好的的工厂AB,只需要测试C,省去工作量。
#include<iostream>
using namespace std;
class Product {
public:
virtual void showType()=0;
virtual ~Product(){}
};
class ProductA:public Product {
public:
virtual void showType() {
cout<<"I am ProductA"<<endl;
}
};
class ProductB:public Product {
public:
virtual void showType() {
cout<<"I am ProductB"<<endl;
}
};
class Factory {
public:
virtual Product* creatProduct()=0;
virtual ~Factory(){}
};
class FactoryA:public Factory {
public:
virtual Product* creatProduct() {
return new ProductA();
}
};
class FactoryB:public Factory {
public:
virtual Product* creatProduct() {
return new ProductB();
}
};
int main() {
Factory* aFactoryA=new FactoryA();
Product* aProductA=aFactoryA->creatProduct();
aProductA->showType();
Factory* aFactoryB=new FactoryB();
Product* aProductB=aFactoryB->creatProduct();
aProductB->showType();
return 0;
}
然而工厂方法模式也有缺点,比如需要很多很多类型的产品,那么你就需要定义很多很多的工厂!增加管理的难度。
三 抽象工厂模式
假设公司原本有两个工厂,一个生产非智能手机芯片,一个生产智能手机芯片,现在想要生产非智能手机电池和智能手机电池,如果按照前面的工厂方法模式,就必须增加额外的两个工厂。现在我们把具有相关性的类型产品放到一个扩大的工厂里:非智能手机芯片和非智能手机电池放到一个工厂;智能手机芯片和智能手机电池放到一个工厂。
#include<iostream>
using namespace std;
class ProductA {
public:
virtual void showType()=0;
virtual ~ProductA() {}
};
class ProductA1:public ProductA {
public:
virtual void showType() {
cout<<"I am ProductA1"<<endl;
}
};
class ProductA2:public ProductA {
public:
virtual void showType() {
cout<<"I am ProductA2"<<endl;
}
};
class ProductB {
public:
virtual void showType()=0;
virtual ~ProductB() {}
};
class ProductB1:public ProductB {
public:
virtual void showType() {
cout<<"I am ProductB1"<<endl;
}
};
class ProductB2:public ProductB {
public:
virtual void showType() {
cout<<"I am ProductB2"<<endl;
}
};
class Factory {//抽象工厂
public:
virtual ProductA* creatProductA()=0;
virtual ProductB* creatProductB()=0;
virtual ~Factory() {}
};
class Factory1:public Factory {//非智能手机工厂
public:
virtual ProductA* creatProductA() {//非智能手机芯片
return new ProductA1();
}
virtual ProductB* creatProductB() {//非智能手机电池
return new ProductB1();
}
};
class Factory2:public Factory {//智能手机工厂
public:
virtual ProductA* creatProductA() {//智能手机芯片
return new ProductA2();
}
virtual ProductB* creatProductB() {//智能手机电池
return new ProductB2();
}
};
int main() {
Factory* aFactory1=new Factory1();
ProductA* aProductA1=aFactory1->creatProductA();
aProductA1->showType();
ProductB* aProductB1=aFactory1->creatProductB();
aProductB1->showType();
Factory* aFactory2=new Factory2();
ProductA* aProductA2=aFactory2->creatProductA();
aProductA2->showType();
ProductB* aProductB2=aFactory2->creatProductB();
aProductB2->showType();
return 0;
}