在簡單工廠模式中講到簡單工廠模式的缺點,有一點是——簡單工廠模式系統(tǒng)難以擴(kuò)展,一旦添加新產(chǎn)品就不得不修改簡單工廠方法,這樣就會造成簡單工廠的實現(xiàn)邏輯過于復(fù)雜,然而本專題介紹的工廠方法模式可以解決簡單工廠模式中存在的這個問題,下面就具體看看工廠模式是如何解決該問題的。
工廠方法模式之所以可以解決簡單工廠的模式,是因為它的實現(xiàn)把具體產(chǎn)品的創(chuàng)建推遲到子類中,此時工廠類不再負(fù)責(zé)所有產(chǎn)品的創(chuàng)建,而只是給出具體工廠必須實現(xiàn)的接口,這樣工廠方法模式就可以允許系統(tǒng)不修改工廠類邏輯的情況下來添加新產(chǎn)品,這樣也就克服了簡單工廠模式中缺點。下面看下工廠模式的具體實現(xiàn)代碼(這里還是以簡單工廠模式中點菜的例子來實現(xiàn)):
namespace 設(shè)計模式之工廠方法模式 { ////// 菜抽象類 /// public abstract class Food { // 輸出點了什么菜 public abstract void Print(); } ////// 西紅柿炒雞蛋這道菜 /// public class TomatoScrambledEggs : Food { public override void Print() { Console.WriteLine("西紅柿炒蛋好了!"); } } ////// 土豆肉絲這道菜 /// public class ShreddedPorkWithPotatoes : Food { public override void Print() { Console.WriteLine("土豆肉絲好了"); } } ////// 抽象工廠類 /// public abstract class Creator { // 工廠方法 public abstract Food CreateFoddFactory(); } ////// 西紅柿炒蛋工廠類 /// public class TomatoScrambledEggsFactory:Creator { ////// 負(fù)責(zé)創(chuàng)建西紅柿炒蛋這道菜 /// ///public override Food CreateFoddFactory() { return new TomatoScrambledEggs(); } } /// /// 土豆肉絲工廠類 /// public class ShreddedPorkWithPotatoesFactory:Creator { ////// 負(fù)責(zé)創(chuàng)建土豆肉絲這道菜 /// ///public override Food CreateFoddFactory() { return new ShreddedPorkWithPotatoes(); } } /// /// 客戶端調(diào)用 /// class Client { static void Main(string[] args) { // 初始化做菜的兩個工廠() Creator shreddedPorkWithPotatoesFactory = new ShreddedPorkWithPotatoesFactory(); Creator tomatoScrambledEggsFactory = new TomatoScrambledEggsFactory(); // 開始做西紅柿炒蛋 Food tomatoScrambleEggs = tomatoScrambledEggsFactory.CreateFoddFactory(); tomatoScrambleEggs.Print(); //開始做土豆肉絲 Food shreddedPorkWithPotatoes = shreddedPorkWithPotatoesFactory.CreateFoddFactory(); shreddedPorkWithPotatoes.Print(); Console.Read(); } } }
使用工廠方法實現(xiàn)的系統(tǒng),如果系統(tǒng)需要添加新產(chǎn)品時,我們可以利用多態(tài)性來完成系統(tǒng)的擴(kuò)展,對于抽象工廠類和具體工廠中的代碼都不需要做任何改動。例如,我們我們還想點一個“肉末茄子”,此時我們只需要定義一個肉末茄子具體工廠類和肉末茄子類就可以。而不用像簡單工廠模式中那樣去修改工廠類中的實現(xiàn)(具體指添加case語句)。具體代碼為:
////// 肉末茄子這道菜 /// public class MincedMeatEggplant : Food { ////// 重寫抽象類中的方法 /// public override void Print() { Console.WriteLine("肉末茄子好了"); } } ////// 肉末茄子工廠類,負(fù)責(zé)創(chuàng)建肉末茄子這道菜 /// public class MincedMeatEggplantFactory : Creator { ////// 負(fù)責(zé)創(chuàng)建肉末茄子這道菜 /// ///public override Food CreateFoddFactory() { return new MincedMeatEggplant(); } } /// /// 客戶端調(diào)用 /// class Client { static void Main(string[] args) { // 如果客戶又想點肉末茄子了 // 再另外初始化一個肉末茄子工廠 Creator minceMeatEggplantFactor = new MincedMeatEggplantFactory(); // 利用肉末茄子工廠來創(chuàng)建肉末茄子這道菜 Food minceMeatEggplant = minceMeatEggplantFactor.CreateFoddFactory(); minceMeatEggplant.Print(); Console.Read(); } }
講解完工廠模式的具體實現(xiàn)之后,讓我們看下工廠模式中各類之間的UML圖:
從UML圖可以看出,在工廠方法模式中,工廠類與具體產(chǎn)品類具有平行的等級結(jié)構(gòu),它們之間是一一對應(yīng)的。針對UML圖的解釋如下:
Creator類:充當(dāng)抽象工廠角色,任何具體工廠都必須繼承該抽象類
TomatoScrambledEggsFactory和ShreddedPorkWithPotatoesFactory類:充當(dāng)具體工廠角色,用來創(chuàng)建具體產(chǎn)品
Food類:充當(dāng)抽象產(chǎn)品角色,具體產(chǎn)品的抽象類。任何具體產(chǎn)品都應(yīng)該繼承該類
TomatoScrambledEggs和ShreddedPorkWithPotatoes類:充當(dāng)具體產(chǎn)品角色,實現(xiàn)抽象產(chǎn)品類對定義的抽象方法,由具體工廠類創(chuàng)建,它們之間有一一對應(yīng)的關(guān)系。
.NET 類庫中也有很多實現(xiàn)了工廠方法的類,例如Asp.net中,處理程序?qū)ο笫蔷唧w用來處理請求,當(dāng)我們請求一個*.aspx的文件時,此時會映射到System.Web.UI.PageHandlerFactory類上進(jìn)行處理,而對*.ashx的請求將映射到System.Web.UI.SimpleHandlerFactory類中(這兩個類都是繼承于IHttpHandlerFactory接口的),關(guān)于這點說明我們可以在“C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\Web.Config”文件中找到相關(guān)定義,具體定義如下:
下面我們就具體看下工廠方法模式在Asp.net中是如何實現(xiàn)的,如果對一個Index.aspx頁面發(fā)出請求時,將會調(diào)用PageHandlerFactory中GetHandler方法來創(chuàng)建一個Index.aspx對象,它們之間的類圖關(guān)系如下:
工廠方法模式通過面向?qū)ο缶幊讨械亩鄳B(tài)性來將對象的創(chuàng)建延遲到具體工廠中,從而解決了簡單工廠模式中存在的問題,也很好地符合了開放封閉原則(即對擴(kuò)展開發(fā),對修改封閉)。
附件:http://down.51cto.com/data/2363464創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務(wù)器,動態(tài)BGP最優(yōu)骨干路由自動選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨有T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動現(xiàn)已開啟,新人活動云服務(wù)器買多久送多久。