最近學習設計模式,對於抽象工廠很是難以理解,就到網上查看一番,碰到一哥們寫的文章,比喻很 貼切,也算是讓我明白了大概。下面是轉載他寫的文章。
他的地址我忘了,很久了。最近整理了一下發到博客上來。
一直覺得設計模式是非常抽象的(事實上MS也是。。。),所以就想把它說的白話點兒,讓人更容易 理解。
關於抽象工廠(Abstract Factory)模式,網上一個非常流行的例子,麥當勞和肯德基的故事。具體怎 麼說的我已經忘了,但是我想自己描述一遍,希望能讓自己加深對設計模式思想的理解,也希望對大家有 所幫助。
既然叫抽象工廠,那一定有工廠(廢話)。那麼我們可以認為麥當勞和肯德基就是生產食物的工廠, 那麼理所當然,漢堡和雞腿是他們共同生產的兩種食物,不管你去MDL還是KDJ,說:我要雞腿,那肯定不 會給你拿來烤羊腿。嘿嘿 。這裡,我們假定麥當勞和肯德基只生產這兩種產品(這很重要,因為抽象工 廠模式的一個很重要的場景就是產品相對穩定,如果要經常新增新產品,那麼需要和另外的設計模式混合 使用或尋求其它解決方案,這裡不贅述)。
情況已經很明顯了,我們是消費者,我們就是客戶,就是產品的消費者,就是程序中對象的調用者。 而麥當勞和肯德基,理所當然的,他們就是工廠,一個叫做麥當勞工廠,一個叫做肯德基工廠,他們是真 正的生產者,而對於我們這些客戶消費者(程序中對象的調用者)來說,不管是去麥當勞還是肯德基,我 們都說一樣的話(我們的要求是穩定的):我要雞腿。只要我們提出這個請求,那麼肯定會得到我們想要 的。而作為工廠(生產者),麥當勞和肯德基都生產雞腿和漢堡,所以抽象出來的抽象工廠都具有生產雞 腿和生產漢堡的功能,這是接口中的兩個方法。因為在這個接口中,還不知道到底要生產誰家的產品,所 以只能返回個抽象的雞腿或漢堡,等到麥當勞或者肯德基工廠生產出來,就知道是誰家的了。(有標志嘛 ,哈哈,這就是動態創建對象)
不管是麥當勞還是肯德基的雞腿或漢堡,它的本質都是雞腿或漢堡,所以可以抽象出來。那麼雞腿就 派生出麥當勞的雞腿和肯德基的雞腿,而漢堡就派生出麥當勞的漢堡和肯德基的漢堡。而對於我們這些客 戶消費者(程序中對象的調用者)來說,不管是去麥當勞還使肯德基,我們都說一樣的話(我們的要求是 穩定的):我要雞腿。只要我們提出這個要求,那麼肯定會得到我們想要的。不管是誰家的雞腿,肯定是 雞腿不會是羊腿。所以,我們只要規定好是雞腿(接口)就行了,而讓工廠去絕對具體的制作過程。我們 只伸手接過來一個雞腿,狠狠的咬一口,恩,真香~:)
到現在為止,我們只和雞腿(抽象的接口)還有抽象工廠(因為我們不管是麥當勞還是肯德基,我們 只要雞腿)打交道。
當我們走向一個快餐店,這個過程就決定了我們到底要哪個工廠來生產雞腿和漢堡。我們可以把我們 消費的習慣存入大腦,每次出門直接取出來,就只管走就行了。也不用看到底是走向了哪裡,反正最後吃 了好多雞腿和漢堡,飽飽的走了。:)哈哈 理論講解完畢,那麼現在看看UML圖。
那麼,現在,大家應該已經看清楚。這張圖是我自己隨手畫的,畫完之後發現,哇,這不就是經典的 AbstractFactory模式的那張圖嗎?現在,你了解嗎?
必勝客來了,也做漢堡和雞腿。那麼怎麼辦呢?非常容易,我們消費者根本不管這些,只管把必勝客 加入我們的大腦(配置文件),需要的時候,直接走進去就行了。僅僅需要添加一個必勝客工廠,必勝客 漢堡,必勝客雞腿,OK,一切搞定。那麼又有人問了,我要喝汽水怎麼辦呢?我偷偷告訴你,這裡不賣~ :)哈哈,希望大家學習愉快,工作愉快!!
以上是我在網上看到一篇仁兄寫的文章,對我思想上的觸發很大。自己琢磨了一會寫出了下面的代碼 。
publicabstractclassKuaiCanFactory //快餐工廠
{
//兩個抽象方法,您吃雞腿呢,還是漢堡呀?因為是抽象出來的,所以不分商家哦!
publicabstractJiTuieatJiTui();
publicabstractHanBaoeatHanBao();
}
//繼續寫類
publicclassMDLFactory:KuaiCanFactory //麥當勞工廠
{
publicoverrideJiTuieatJiTui()
{
returnnewMDLJiTui();
}
publicoverrideHanBaoeatHanBao()
{
returnnewMDLHanBao();
}
}
//有了麥當勞當然少不了KFC啦。
//肯德基工廠及麥當勞工廠都實現了eatJiTui(),eatHanBao()方法。
publicclassKDJFactory:KuaiCanFactory
{
publicoverrideJiTuieatJiTui()
{
returnnewKDJJiTui();
}
publicoverrideHanBaoeatHanBao()
{
returnnewKDJHanBao();
}
}
//下面就到食物了。。
publicabstractclassHanBao //漢堡抽象類
{
publicabstractvoidgetHanBao();
}
publicclassMDLHanBao:HanBao//具體的麥當勞漢堡
{
publicoverridevoidgetHanBao()
{
Console.WriteLine("麥當勞漢堡");
}
}
publicclassKDJHanBao:HanBao //具體的肯德基漢堡
{
publicoverridevoidgetHanBao()
{
Console.WriteLine("肯德基漢堡");
}
}
publicabstractclassJiTui //雞腿抽象類
{
publicabstractvoidgetJiTui();
}
publicclassKDJJiTui:JiTui //具體的肯德基雞腿
{
publicoverridevoidgetJiTui()
{
Console.WriteLine("肯德基雞腿");
}
}
classMDLJiTui:JiTui //具體的麥當勞雞腿
{
publicoverridevoidgetJiTui()
{
Console.WriteLine("麥當勞雞腿");
}
}
//這樣就大功告成,客戶去快餐店吃雞腿,並不關心他們怎麼拿出來的,只需要大吼一聲“我吃雞腿” ,就OK了。
staticvoidMain(string[]args)
{
//這裡或許使用簡單工廠來處理選擇商店更好
KuaiCanFactoryKC=newKDJFactory();//想吃KFC的雞腿,那麼就去KFC。
JiTuijt=KC.eatJiTui();//想吃雞腿了,那麼就告訴KC(快餐店)
jt.getJiTui();//雞腿拿來咯~~……
HanBaohb=KC.eatHanBao();//想吃漢堡
hb.getHanBao();
KC=newMDLFactory();
jt=KC.eatJiTui();
jt.getJiTui();
hb=KC.eatHanBao();
hb.getHanBao();
}
輸出結果:
肯德基雞腿
肯德基漢堡
麥當勞雞腿
麥當勞漢堡
飽了~~~~希望別吃壞了肚子。。要是哪不對,就給我留言,謝謝!!!