描述:
抽象工厂是一个适用于创建一系列相关的产品的创建性模型.比如设计模式书中经常讲的那个例子-支持多视感窗口的工具包,比如windows和motif风格,这个是风格族.每种风格下面都有些标准的产品族,象BUTTON, TextBox, ListBox等.试想一下,如果直接在client中指定具体产品和它的风格,那么会出现2*3 = 6中组合,如果新增一种产品或风格,那么组合会以倍数增加,看来这样的做法是很愚蠢的.所以还是以面向对象的几个原则来分析一下这个问题,首先可以看出此问题有两个方面的变化,一个是窗口风格的变化,另一个是产品的变化.而且在程序中一般都会出现相同风格的产品,windows风格的应用程序绝对不会出现一个motif风格的按钮.上面的两点足以说明,客户端只需要指定一个风格,然后创建时就自然的创建出这个风格的产品族来了.而每种产品应该有个一致的接口,不会因为风格的不同接口也不同.所以客户端得到的产品不管是什么风格的都会一致的对待.
静态结构图:
这个模式的好处:
增加一个产品,只需增加一个抽象产品类和各个风格的这个产品的具体类.而对别的没有影响.
增加一个风格,首先要增加一个具体工厂类,然后在每个产品中增加一个支持这个风格的具体产品类.
松散了client直接创建产品带来的耦合性,和复杂性(因为直接创建产品将会得到乘积数量的产品).
什么时候使用:
一个系统要独立于它的产品的创建,组合和使用时.
一个系统有一系列产品,而每个产品都有不同的实现(风格),而在一个具体的应用中只能配置一种实现时(风格).
例子:
麦当劳和肯德基都是做快餐的,假如你现在你要做一个这样的企业的MIS系统,你必须让这个系统通用,而且这样的公司都有一系列的相关产品所以你会考虑用抽象工厂来创建产品系列(象汉堡,可乐等),其中公司就是风格族,做的那些食品就是产品族.而且在一个应用中只有同一个风格的产品出现.不会出现肯德基的瓶子里装的是麦当劳的可乐.下面是示意代码:
// Abstract Factory
class FoodFactory
{
virtual Homburg* CreateHomburg() = 0;
virtual Kele* CreateKele() = 0;
}
// Concrete Factory
class KFCFactory : public FoodFactory
{
Homburg* CreateHomburg()
{
cout << "use KFC factory create Homburg" << endl;
return new KFCHomburg;
}
Kele* CreateKele()
{
cout << "use KFC factory create Kele" << endl;
return new KFCKele;
}
}
// Concrete Factory
class MDLFactory : public FoodFactory
{
Homburg* CreateHomburg()
{
cout << "use MDL factory create Homburg" << endl;
return new MDLHomburg;
}
Kele* CreateKele()
{
cout << "use MDL factory create Kele" << endl;
return new MDLKele;
}
}
// abstract Homburg
class Homburg
{
virtual int GetFlavour() = 0;
virtual void DrawMe() = 0;
}
// Concrete Homburg
class KFCHomburg : public Homburg
{
virtual int GetFlavour()
{
cout << "KFC Homburg very good!" << endl;
return 80;
}
virtual void DrawMe()
{
cout << "KFC Homburg drawing" << endl;
}
}
// Concrete Homburg
class MDLHomburg : public Homburg
{
virtual int GetFlavour()
{
cout << "MDL Homburg better!" << endl;
return 90;
}
virtual void DrawMe()
{
cout << "MDL Homburg drawing" << endl;
}
}
//Abstract Kele
class Kele
{
virtual void AddIce() = 0 ;
virtual DrawMe() = 0;
}
// Concrete Kele
class KFCKele : public Kele
{
virtual void AddIce()
{
cout << "KFC Kele Add Ice" << endl;
}
virtual DrawMe()
{
cout << "KFC Kele drawing" << endl;
}
}
// Concrete Kele
class MDLKele : public Kele
{
virtual void AddIce()
{
cout << "MDL Kele Add Ice" << endl;
}
virtual DrawMe()
{
cout << "MDL Kele drawing" << endl;
}
}
int main(int argc, char* argv[])
{
FoodFactory* foodFactory = new KFCFactory;
Homburg* homb = foodFactory->CreateHomburg();
Kele* kele = foodFactory->CreateKele();
cout << homb->GetFlavour()<< endl;
homb->DrawMe();
kele->AddIce();
kele->DrawMe();
return 0;
}
相关别的模式:
前面说过的工厂方法和抽象工厂的区别是什么,各适用于什么场景中.
如果有一系列产品族则用抽象工厂,如果只有一种类型的产品则用工厂方法.
参考文献:
《设计模式精解》清华大学出版社,熊杰译。
《设计模式可复用面向对象软件的基础》机械工业出版社,四人团著。