AbstractFactory模式:
AbstractFactory模式用来提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
在以下情况可以使用Abstract Factory模式
• 一个系统要独立于它的产品的创建、组合和表示时。
• 一个系统要由多个产品系列中的一个来配置时。
• 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
• 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
正如Factory模式中所说,Factory模式无法为不同类型的类提供一个统一的对象创建接口,而AbstractFactory正好可以解决这个问题。
这里引用《常见设计模式的解析和实现(C++)》一文中的例子,比如,同样是鸡腿(ProductA)和汉堡(ProductB),它们都可以有商店出售(AbstractFactory),但是有不同的实现,有肯德基(ConcreateFactory1)和麦当劳(ConcreateFactory2)两家生产出来的不同风味的鸡腿和汉堡(也就是ProductA 和ProductB的不同实现).而负责生产汉堡和鸡腿的就是之前提过的Factory模式了.
抽象工厂需要特别注意的地方就是区分不同类型的产品和这些产品的不同实现.显而易见的,如果有n种产品同时有m中不同的实现,那么根据乘法原理可知有n*m个Factory模式的使用.
下面是AbstractFactory的代码实现:
//Product.h
#ifndef _PRODUCT_H_
#define _PRODUCT_H_
// 鸡腿
class AbstractProductA
{
public:
virtual ~AbstractProductA();
protected:
AbstractProductA();
private:
};
// 汉堡
class AbstractProductB
{
public:
virtual ~AbstractProductB();
protected:
AbstractProductB(); private:
};
// 肯德基的鸡腿
class ProductA1:public AbstractProductA
{
public:
ProductA1();
~ProductA1();
protected: private:
};
// 麦当劳的鸡腿
class ProductA2:public AbstractProductA
{
public:
ProductA2();
~ProductA2();
protected: private:
};
// 肯德基的汉堡
class ProductB1:public AbstractProductB
{
public:
ProductB1();
~ProductB1();
protected:
private:
};
// 麦当劳的汉堡
class ProductB2:public AbstractProductB
{
public:
ProductB2();
~ProductB2();
protected: private:
};
#endif //~_PRODUCT_H_ECT_H_
//Product.cpp
#include "Product.h"
#include <iostream>
using namespace std;
AbstractProductA::AbstractProductA()
{ }
AbstractProductA::~AbstractProductA()
{ }
AbstractProductB::AbstractProductB()
{
}
AbstractProductB::~AbstractProductB()
{
}
ProductA1::ProductA1()
{
cout<<"ProductA1...肯德基的鸡腿"<<endl;
}
ProductA1::~ProductA1()
{
}
ProductA2::ProductA2()
{
cout<<"ProductA2...麦当劳的鸡腿"<<endl;
}
ProductA2::~ProductA2()
{
}
ProductB1::ProductB1()
{
cout<<"ProductB1...肯德基的汉堡"<<endl;
}
ProductB1::~ProductB1()
{
}
ProductB2::ProductB2()
{
cout<<"ProductB2...麦当劳的汉堡"<<endl;
}
ProductB2::~ProductB2()
{
}
//AbstractFactory.h
#ifndef _ABSTRACTFACTORY_H_
#define _ABSTRACTFACTORY_H_
class AbstractProductA;
class AbstractProductB;
// 快餐店
class AbstractFactory
{
public:
virtual ~AbstractFactory();
virtual AbstractProductA* CreateProductA() = 0;
virtual AbstractProductB* CreateProductB() = 0;
protected:
AbstractFactory();
private:
};
// 肯德基
class ConcreteFactory1:public AbstractFactory
{
public:
ConcreteFactory1();
~ConcreteFactory1();
AbstractProductA* CreateProductA();
AbstractProductB* CreateProductB();
protected:
private:
};
// 麦当劳
class ConcreteFactory2:public AbstractFactory
{
public:
ConcreteFactory2();
~ConcreteFactory2();
AbstractProductA* CreateProductA();
AbstractProductB* CreateProductB();
protected:
private:
};
#endif //~_ABSTRACTFACTORY_H_
//AbstractFactory.cpp
#include "AbstractFactory.h"
#include "Product.h"
#include <iostream>
using namespace std;
AbstractFactory::AbstractFactory()
{
}
AbstractFactory::~AbstractFactory()
{
}
ConcreteFactory1::ConcreteFactory1()
{
}
ConcreteFactory1::~ConcreteFactory1()
{
}
AbstractProductA* ConcreteFactory1::CreateProductA()
{
return new ProductA1();
}
AbstractProductB* ConcreteFactory1::CreateProductB()
{
return new ProductB1();
}
ConcreteFactory2::ConcreteFactory2()
{
}
ConcreteFactory2::~ConcreteFactory2()
{
}
AbstractProductA* ConcreteFactory2::CreateProductA()
{
return new ProductA2();
}
AbstractProductB* ConcreteFactory2::CreateProductB()
{
return new ProductB2();
}
//main.cpp
#include "AbstractFactory.h"
#include <iostream>
using namespace std;
int main(int argc,char* argv[])
{
AbstractFactory* cf1 = new ConcreteFactory1();
cf1->CreateProductA();
cf1->CreateProductB();
AbstractFactory* cf2 = new ConcreteFactory2();
cf2->CreateProductA();
cf2->CreateProductB();
return 0;
}
AbstractFactory模式是为创建一组(有多类)相关或依赖的对象提供创建接口,而Factory模式正如我在相应的文档中分析的是为一类对象提供创建接口或延迟对象的创建到子类中实现。并且可以看到,AbstractFactory模式通常都是使用Factory模式实现(ConcreteFactory1)。
AbstractFactory模式通常是在运行时刻再创建一个ConcreteFactory类的实例,这个具体的工厂再创建具有特定实现的铲平对象,也就是说,为创建不同的产品对象,客户端应使用不同的具体工厂。并且它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体的工厂的实现分离,不会出现在客户代码中。
再参考《大话设计模式》中关于AbstractFactory的例子,结合上面的实现,我们有更进一步的思考:可不可以在程序中写明“如果是汉堡就去实例化汉堡的类,如果是鸡腿就去实例化鸡腿的类?”意思是如果传进来一个字符串“鸡腿”就实例化鸡腿类,如果传进来一个字符串“汉堡”就实例化汉堡类。C#中有语言内部支持所谓的“反射”,而C++语言是不内置“反射”功能的。具体说明和实现,见下篇。