在抽象原廠模式中,我引用從網上看來的一篇例子來說明。
隨著時間的推移,走過的地方越來越多,你天南海北的朋友也越來越多。你發現菜原來還分了許多菜系,魯菜、粵菜、湘菜等等, 你招待
不同的朋友要用不同的菜系,這下難辦了,你的廚師都是魯菜風味,怎麼辦,廣東的朋友來了吃不慣。現在我們再回到簡單原廠模式,我們把
紅燒肉再向下繼承,產生魯菜紅燒肉、粵菜紅燒肉、湘菜紅燒肉;清蒸魚向下繼承為魯菜清蒸魚、粵菜清蒸魚、湘菜清蒸魚,其它也以此類
推。我們也修改一下這個類,不讓其返回食物基類,而是返回紅燒肉、清蒸魚這一層次,並把這些方法抽象化,作為菜系工廠基類,然後再從
此基類繼承出,魯菜工廠、粵菜工廠、湘菜工廠等等,再由這些具體工廠實現建立具體菜的工作,哈哈你如果招待廣東朋友就用粵菜工廠,返
回的就是一桌粵菜菜系的紅燒肉、清蒸魚了,你的廣東朋友一定會吃的非常合乎胃口了。噢,非常好,你已經實現了抽象原廠模式了。結構模
型圖也變成了的樣子了。
現在可以看到,想新來做一個菜系,只需新聘請一個廚師就可以了,多麼完美,但是如果你想新增加一個菜就變得非常困難了。
實現代碼:
//產品基類
#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基類(在原廠模式
中它們為具體實作類別,這裡變成了基類)了。此時工廠的抽象和簡單工廠中的Factory 方法也很類似,就是這些特徵區使其別於原廠模式而變成抽
象原廠模式了,因此抽象工廠解決的是建立一系列有共同風格的產品(魯菜還是粵菜),而Factory 方法模式解決的建立有共同特徵的一系列產品
(紅燒肉、清蒸魚它們都是食物)。當然簡單工廠的缺陷在抽象工廠中又再次出現了,我要新增加一個產品,工廠抽象介面就要改變了。因此
抽象工廠並不比原廠模式完美,只不過是各自的適用領域不同而已。其實,這裡如果把抽象原廠模式的介面返回產品A和產品B的共同基類
(原廠模式返回的參數),你會發現,奇怪這個模式怎麼這麼眼熟,它不是恰恰退化成原廠模式了。
類模式與對象模式的區別討論:先看定義類“模式使用繼承關係,把對象的建立延遲的子類,對象模式把對象的建立延遲到另一個對象
中”。 分析:首先它們建立對象都不是在基類中完成,都是在子類中實現,因此都符合類模式的概念;但是原廠模式的建立產品對象是在編
譯期決定的,要調用某個工廠固定的,而抽象原廠模式對產品的建立是在運行時動態決定的,只有到運行時才確定要調用那個工廠,調用工廠
隨運行環境而改變。
適用性:
- 一個系統要獨立於它的產品的建立、組合和表示時
- 一個系統要由多個 產品系列中的一個來配置時
- 當你要強調一個系列相關的產品對象的設計以便進行聯合使用時
- 當你提供一個產品類庫,而只想顯示它們的介面而不是實現時。