千百年來,關于“空中花園”有一個美麗動人的傳說。新巴比倫國王尼布甲尼撒二世娶了米底的公主安美依迪絲為王后。公主美麗可人,深得國王的寵愛。可是時間一長,公主愁容漸生。尼布甲尼撒不知何故。公主說:“我的家鄉山巒疊翠,花草叢生。而這里是一望無際的巴比倫平原,連個小山丘都找不到,我多么渴望能再見到我們家鄉的山嶺和盤山小道啊!”原來公主得了思鄉病。于是,尼布甲尼撒二世令工匠按照米底山區的景色,在他的宮殿里,建造了層層疊疊的階梯型花園,上面栽滿了奇花異草,并在園中開辟了幽靜的山間小道,小道旁是潺潺流水。工匠們還在花園中央修建了一座城樓,矗立在空中,巧奪天工的園林景色終于博得公主的歡心。故事講到這里,在我們的故事中蘊藏著怎樣的設計模式呢?今天這篇博文的內容就從我們美麗動人的傳說空中花園開始!
如果空中花園中只種花,那么就用[簡單工廠](http://blog.csdn.net/u010850027/article/details/21878639)就可以了,如果公主喜歡各種各樣的花,種類比較繁多,我們就需要用工廠方法,把公共有的東西抽象出來,再者如果公主想要擴大花園的規模,一個在安徽一個在河北,這樣工廠方法也就無法實現了,這個時候,就需要用到抽象工廠,把各種各樣的植物,又組成一個空中花園。我們先來看一下工廠方法模式模式的結構圖:
? ? ? ??
在前面的博文中,我們學習過[簡單工廠模式](http://blog.csdn.net/u010850027/article/details/21878639),簡單工廠是一個工廠只生產一類的產品,面對的是具體的類,工廠方法是可以生產不同的產品,把公共的方法抽象出來,然后進行創建各種各樣的產品.抽象工廠把幾種產品劃出共同的東西,把相互依賴的對象抽象出來,只要實現這些接口就可以得到不同的產品,簡單工廠模式系統難以擴展,一旦添加新產品就不得不修改簡單工廠方法,這樣就會造成簡單工廠的實現邏輯過于復雜,下面就具體看看工廠模式是如何解決該問題的。 工廠方法模式之所以可以解決簡單工廠的模式,是因為它的實現把具體產品的創建推遲到子類中,此時工廠類不再負責所有產品的創建,而只是給出具體工廠必須實現的接口,這樣工廠方法模式就可以允許系統不修改工廠類邏輯的情況下來添加新產品,這樣也就克服了簡單工廠模式中缺點。下面看下工廠模式的具體實現代碼(這里還是以簡單工廠模式中點菜的例子來實現:
~~~
namespace?設計模式之工廠方法模式??
{??
????///???
????///?菜抽象類??
????///???
????public?abstract?class?Food??
????{??
????????//?輸出顧客點了什么菜??
????????public?abstract?void?Print();??
????}??
?????
????///?酸辣土豆絲這道菜??
?????
????public?class?ChiliSourPotatod:?Food??
????{??
????????public?override?void?Print()??
????????{??
????????????Console.WriteLine("酸辣土豆絲出鍋!");??
????????}??
????}??
????///???
????///?姜汁皮蛋這道菜??
????///???
????public?class?PreservedEggSinGingerSauce?:?Food??
????{??
????????public?override?void?Print()??
????????{??
????????????Console.WriteLine("姜汁皮蛋");??
????????}??
????}??
????///???
????///?抽象工廠類??
????///???
????public?abstract?class?Creator??
????{??
????????//?工廠方法??
????????public?abstract?Food?CreateFoddFactory();??
????}??
????///???
????///?酸辣土豆絲工廠類??
????///???
????public?class??ChiliSourPotatod:Creator??
????{??
????????///???
????????///?負責創建酸辣土豆絲這道菜??
????????///???
????????///???
????????public?override?Food?CreateFoddFactory()??
????????{??
????????????return?new??ChiliSourPotatod();??
????????}??
????}??
????///???
????///?姜汁皮蛋工廠類??
????///???
????public?class?PreservedEggSinGingerSauceFactory:Creator??
????{??
????????///???
????????///?負責創建姜汁皮蛋這道菜??
????????///???
????????///???
????????public?override?Food?CreateFoddFactory()??
????????{??
????????????return?newPreservedEggSinGingerSauce();??
????????}??
????}??
????///???
????///?客戶端調用??
????///???
????class?Client??
????{??
????????static?void?Main(string[]?args)??
????????{??
????????????//?初始化做菜的兩個工廠()??
????????????Creator?ChiliSourPotatodFactory?=?new?ChiliSourPotatodFactory();??
????????????Creator?PreservedEggSinGingerSauceFactory?=?new??PreservedEggSinGingerSauceFactory();??
????????????//?開始做酸辣土豆絲??
????????????Food?ChiliSourPotatod?=?tomatoScrambledEggsFactory.CreateFoddFactory();??
????????????ChiliSourPotatod.Print();??
????????????//開始做姜汁皮蛋??
????????????FoodPreservedEggSinGingerSauce?=PreservedEggSinGingerSauceFactory.CreateFoddFactory();??
????????????PreservedEggSinGingerSauce.Print();??
????????????Console.Read();??
????????}??
????}??
}??
~~~
使用工廠方法實現的系統,如果系統需要添加新產品時,我們可以利用多態性來完成系統的擴展,對于抽象工廠類和具體工廠中的代碼都不需要做任何改動。例如,我們我們還想點一個“黃瓜炒雞蛋”,此時我們只需要定義一個黃瓜炒雞蛋具體工廠類和黃瓜炒雞蛋類就可以。而不用像簡單工廠模式中那樣去修改工廠類中的實現,具體代碼如下所示:
~~~
///???
????///?黃瓜炒雞蛋這道菜??
????///???
????public?class?ScrambleEggWithCucumber?:?Food??
????{??
????????///???
????????///?重寫抽象類中的方法??
????????///???
????????public?override?void?Print()??
????????{??
????????????Console.WriteLine("黃瓜炒雞蛋好了");??
????????}??
????}??
?///???
????///?黃瓜炒雞蛋工廠類,負責創建黃瓜炒雞蛋這道菜??
????///???
????public?classScrambleEggWithCucumberFactory?:?Creator??
????{??
????????///???
????????///?負責創建黃瓜炒雞蛋這道菜??
????????///???
????????///???
????????public?override?Food?CreateFoddFactory()??
????????{??
????????????return?new?ScrambleEggWithCucumber();??
????????}??
????}??
????///???
????///?客戶端調用??
????///???
????class?Client??
????{??
????????static?void?Main(string[]?args)??
????????{??
??????????????????????
????????????//?如果客戶又想點黃瓜炒雞蛋了??
????????????//?再另外初始化一個黃瓜炒雞蛋工廠??
????????????Creator?ScrambleEggWithCucumberFactor?=?new?ScrambleEggWithCucumberFactory();??
????????????//?利用黃瓜炒雞蛋工廠來創建黃瓜炒雞蛋這道菜??
????????????Food?ScrambleEggWithCucumber?=?ScrambleEggWithCucumberFactor.CreateFoddFactory();??
????????????ScrambleEggWithCucumber.Print();??
????????????Console.Read();??
????????}??
????}??
~~~
? ? ? ? ?
簡單工廠:嚴格說并不是一個設計模式。簡單工廠沒有抽象類,只有一個具體工廠類如MyFactory,然后MyFactory里面有個工廠方法CreateProduct返回一個基類產品,具體返回什么具體實例通過傳入參數然后用case判斷。用手機生產做個例子:比如魅族簡單工廠就是只有MeizuFactory工廠類,工廠方法就是CreateMeizuPhone,參數是Meizu手機型號,根據不同型號創建不同的Meizu手機(使用case)。很明顯的缺點就是Meizu每發明一個新型號的手機都需要修改簡單工廠類(增加case判斷),違反了封閉修改,開放擴展原則。
工廠方法:該模式有一個抽象基類和若干個派生的具體工廠類,基類定義了一個虛工廠方法返回指定產品類的基類,派生類需要實現該虛方法并創建具體產品類返回。注意工廠方法的每個具體工廠只負責返回一種產品類。同樣以手機生產做例子:Meizu工廠方法模式有一個工廠基類MeizuFactory,注意此工廠和上面不一樣,是抽象的。該類定義一個虛工廠方法CreateMeizuPhone,該方法返回MeizuPhone基類。然后不同型號的手機對應一個該型號的手機工廠,這樣的優點就是,新出一個Meizu手機型號,只需派生一個該型號的工廠而無需修改原來的代碼。符合封閉修改,開放擴展原則。設計之旅,未完待續......
? ? ? ? ?