在抽象工厂模式中,我引用从网上看来的一篇例子来说明。
随着时间的推移,走过的地方越来越多,你天南海北的朋友也越来越多。你发现菜原来还分了许多菜系,鲁菜、粤菜、湘菜等等, 你招待
不同的朋友要用不同的菜系,这下难办了,你的厨师都是鲁菜风味,怎么办,广东的朋友来了吃不惯。现在我们再回到简单工厂模式,我们把
红烧肉再向下继承,生成鲁菜红烧肉、粤菜红烧肉、湘菜红烧肉;清蒸鱼向下继承为鲁菜清蒸鱼、粤菜清蒸鱼、湘菜清蒸鱼,其它也以此类
推。我们也修改一下这个类,不让其返回食物基类,而是返回红烧肉、清蒸鱼这一层次,并把这些方法抽象化,作为菜系工厂基类,然后再从
此基类继承出,鲁菜工厂、粤菜工厂、湘菜工厂等等,再由这些具体工厂实现创建具体菜的工作,哈哈你如果招待广东朋友就用粤菜工厂,返
回的就是一桌粤菜菜系的红烧肉、清蒸鱼了,你的广东朋友一定会吃的非常合乎胃口了。噢,非常好,你已经实现了抽象工厂模式了。结构模
型图也变成了的样子了。
现在可以看到,想新来做一个菜系,只需新聘请一个厨师就可以了,多么完美,但是如果你想新增加一个菜就变得非常困难了。
实现代码:
//产品基类
#include <iostream>
class FoodProduct
{
public:
FoodProduct(void);
~FoodProduct(void);
virtual void Delicious();
};
//红烧鱼类
class BraisingFish :public FoodProduct
{
public:
BraisingFish(void);
~BraisingFish(void);
virtual void Delicious();
};
//清蒸鱼类
class SteamedFish :public FoodProduct
{
public:
SteamedFish(void);
~SteamedFish(void);
virtual void Delicious();
};
//川式清蒸鱼
class ChuanBraisingFish :public BraisingFish
{
public:
ChuanBraisingFish(void);
~ChuanBraisingFish(void);
virtual void Delicious();
};
//鲁式清蒸鱼
class LuBraisingFish :public BraisingFish
{
public:
LuBraisingFish(void);
~LuBraisingFish(void);
virtual void Delicious();
};
//川(鲁)式红烧鱼类的写法与清蒸鱼类相同
//下面实现烹饪工厂
//烹饪总工厂
class CookFactory
{
public:
CookFactory(void);
~CookFactory(void);
virtual BraisingFish *CookBraisingFish();
virtual SteamedFish *CookSteamedFish();
};
//鲁菜工厂
class LuCookFactory :public CookFactory
{
public:
LuCookFactory(void);
~LuCookFactory(void);
virtual BraisingFish *CookBraisingFish();
virtual SteamedFish *CookSteamedFish();
};
//鲁菜工厂的实现
BraisingFish *LuCookFactory::CookBraisingFish()
{
std::cout<<"The Lu BraisingFish is Cooked!"<<std::endl;
return new LuBraisingFish();
}
SteamedFish *LuCookFactory::CookSteamedFish()
{
std::cout<<"The Lu StramedFish is Cooked!"<<std::endl;
return new LuSteamedFish();
}
//川菜工厂
class ChuanCookFactory :public CookFactory
{
public:
ChuanCookFactory(void);
~ChuanCookFactory(void);
virtual BraisingFish *CookBraisingFish();
virtual SteamedFish *CookSteamedFish();
};
//川菜工厂的实现
BraisingFish *ChuanCookFactory::CookBraisingFish()
{
std::cout<<"The Chuan BraisingFish is Cooked!"<<std::endl;
return new ChuanBraisingFish();
}
SteamedFish *ChuanCookFactory::CookSteamedFish()
{
std::cout<<"The Chuan SteamedFish is Cooked!"<<std::endl;
return new ChuanSteamedFish();
}
//下面是客户端的实现
int main(void)
{
CookFactory *cookFac = new LuCookFactory();
BraisingFish *braFish = cookFac->CookBraisingFish();
braFish->Delicious();
std::cout<<"******************************************/n";
delete braFish;
SteamedFish *steFish = cookFac->CookSteamedFish();
steFish->Delicious();
std::cout<<"******************************************/n";
delete steFish;
delete cookFac;
cookFac = new ChuanCookFactory();
braFish = cookFac->CookBraisingFish();
braFish->Delicious();
std::cout<<"******************************************/n";
delete braFish;
steFish = cookFac->CookSteamedFish();
steFish->Delicious();
delete steFish;
system("pause");
return 0;
}
至此,抽象工厂模式完成。
现在可以和工厂模式对比一下,抽象工厂返回的接口不再是产品A和产品B的共同基类Product了,而是产品A、产品B基类(在工厂模式
中它们为具体实现类,这里变成了基类)了。此时工厂的抽象和简单工厂中的工厂方法也很类似,就是这些特征区使其别于工厂模式而变成抽
象工厂模式了,因此抽象工厂解决的是创建一系列有共同风格的产品(鲁菜还是粤菜),而工厂方法模式解决的创建有共同特征的一系列产品
(红烧肉、清蒸鱼它们都是食物)。当然简单工厂的缺陷在抽象工厂中又再次出现了,我要新增加一个产品,工厂抽象接口就要改变了。因此
抽象工厂并不比工厂模式完美,只不过是各自的适用领域不同而已。其实,这里如果把抽象工厂模式的接口返回产品A和产品B的共同基类
(工厂模式返回的参数),你会发现,奇怪这个模式怎么这么眼熟,它不是恰恰退化成工厂模式了。
类模式与对象模式的区别讨论:先看定义类“模式使用继承关系,把对象的创建延迟的子类,对象模式把对象的创建延迟到另一个对象
中”。 分析:首先它们创建对象都不是在基类中完成,都是在子类中实现,因此都符合类模式的概念;但是工厂模式的创建产品对象是在编
译期决定的,要调用某个工厂固定的,而抽象工厂模式对产品的创建是在运行时动态决定的,只有到运行时才确定要调用那个工厂,调用工厂
随运行环境而改变。
适用性:
- 一个系统要独立于它的产品的创建、组合和表示时
- 一个系统要由多个 产品系列中的一个来配置时
- 当你要强调一个系列相关的产品对象的设计以便进行联合使用时
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时。