使用設(shè)計(jì)模式中的工廠方法模式進(jìn)行C#編程的示例講解
簡(jiǎn)介
工廠方法模式是什么?為什么要有工廠方法模式,不是有了簡(jiǎn)單工廠模式了嗎??jī)蓚€(gè)模式都有工廠,那有什么不同呢?功工廠方式模式是怎樣實(shí)現(xiàn)的?OK,帶著這些問(wèn)題,繼續(xù)看下面文章。
工廠方法模式是對(duì)簡(jiǎn)單工廠模式的擴(kuò)展,可以說(shuō)是用來(lái)完善簡(jiǎn)單工廠模式的缺點(diǎn)的,什么缺點(diǎn)呢?在上一篇文章已經(jīng)說(shuō)過(guò):擴(kuò)展性極差。你想一下,如果在簡(jiǎn)單工廠模式中,如果董事會(huì)決定想添加一個(gè)玩具生產(chǎn),叫熊貓玩具,那么全廠該做的事有哪些呢?
1.告訴銷(xiāo)售經(jīng)理:我們準(zhǔn)備要添加一個(gè)熊貓玩具,可以提供給用戶的。
2.到工廠作坊里面,告訴工人要做熊貓工具。
在現(xiàn)實(shí)生活中確實(shí)是這樣的,因?yàn)樵诂F(xiàn)實(shí)生活中這樣做不會(huì)造成很大的影響,但是在程序世界里面就大件事了,首先如果這樣做可能會(huì)破壞工廠作坊的內(nèi)部結(jié)構(gòu),造成BUG,還有的是這樣改就等于修改了源代碼,不斷添加新的工具,不斷修改源代碼,有沒(méi)想過(guò):如果添加100個(gè)玩具,那個(gè)判斷命令里面得有多少個(gè)case???,程序里面不同現(xiàn)實(shí)生活,創(chuàng)建新的大工廠是不用錢(qián)的。。所以要用好這個(gè)特點(diǎn),下面我們就對(duì)上篇文章中的玩具廠進(jìn)行一次大規(guī)模的改造,讓其實(shí)現(xiàn)工程方法模式?。。。。?/p>
是不是很激動(dòng),,我也很激動(dòng)。。。
首先,玩具工廠原址變成指揮站,專(zhuān)門(mén)指揮新工廠的建立的,然后指揮站附近新建三個(gè)小型工廠:玩具貓工作廠,玩具狗工作廠,玩具熊貓工作廠。各自的工作坊只會(huì)做各自的玩具。指揮戰(zhàn)中有玩具的生產(chǎn)計(jì)劃書(shū),每個(gè)小型工廠都需要按照指揮部的工作計(jì)劃書(shū)來(lái)做玩具(當(dāng)然計(jì)劃書(shū)只要求了一部分特色功能,各個(gè)廠的小玩具到底怎么做,,還要自己做的)。好了,就這么簡(jiǎn)單,全新的工廠開(kāi)發(fā)模式出來(lái)了,這樣做的好處是什么呢?我們看一下如果新提供鱷魚(yú)玩具到底該做什么:
1.新建一個(gè)小型工廠(鱷魚(yú)工廠)
2.去問(wèn)指揮部那一份制作計(jì)劃書(shū),讓鱷魚(yú)有計(jì)劃書(shū)中的基本功能(這樣才能通過(guò)考核然后上線出售)
2.鱷魚(yú)工廠自己購(gòu)買(mǎi)鱷魚(yú)的制作指南去制作鱷魚(yú)玩具。
現(xiàn)在是不是發(fā)現(xiàn),如果給程序干這事,簡(jiǎn)直就是,,,超級(jí)簡(jiǎn)單,不會(huì)擾亂其他工廠的生產(chǎn)秩序。當(dāng)有客戶來(lái)買(mǎi)玩具的時(shí)候,他們到指揮站說(shuō):我要一只小狗,指揮站說(shuō):給錢(qián)后請(qǐng)到哪里哪里拿(小狗工廠),然后客戶走過(guò)去拿就是了。
工廠方法模式的實(shí)現(xiàn)
工廠方法模式之所以可以解決簡(jiǎn)單工廠的模式,是因?yàn)樗膶?shí)現(xiàn)把具體產(chǎn)品的創(chuàng)建推遲到子類(lèi)中,此時(shí)工廠類(lèi)不再負(fù)責(zé)所有產(chǎn)品的創(chuàng)建,而只是給出具體工廠必須實(shí)現(xiàn)的接口,這樣工廠方法模式就可以允許系統(tǒng)不修改工廠類(lèi)邏輯的情況下來(lái)添加新產(chǎn)品,這樣也就克服了簡(jiǎn)單工廠模式中缺點(diǎn)。下面看下工廠模式的具體實(shí)現(xiàn)代碼(這里還是以簡(jiǎn)單工廠模式中點(diǎn)菜的例子來(lái)實(shí)現(xiàn)):
namespace 設(shè)計(jì)模式之工廠方法模式
{
/// <summary>
/// 菜抽象類(lèi)
/// </summary>
public abstract class Food
{
// 輸出點(diǎn)了什么菜
public abstract void Print();
}
/// <summary>
/// 西紅柿炒雞蛋這道菜
/// </summary>
public class TomatoScrambledEggs : Food
{
public override void Print()
{
Console.WriteLine("西紅柿炒蛋好了!");
}
}
/// <summary>
/// 土豆肉絲這道菜
/// </summary>
public class ShreddedPorkWithPotatoes : Food
{
public override void Print()
{
Console.WriteLine("土豆肉絲好了");
}
}
/// <summary>
/// 抽象工廠類(lèi)
/// </summary>
public abstract class Creator
{
// 工廠方法
public abstract Food CreateFoddFactory();
}
/// <summary>
/// 西紅柿炒蛋工廠類(lèi)
/// </summary>
public class TomatoScrambledEggsFactory:Creator
{
/// <summary>
/// 負(fù)責(zé)創(chuàng)建西紅柿炒蛋這道菜
/// </summary>
/// <returns></returns>
public override Food CreateFoddFactory()
{
return new TomatoScrambledEggs();
}
}
/// <summary>
/// 土豆肉絲工廠類(lèi)
/// </summary>
public class ShreddedPorkWithPotatoesFactory:Creator
{
/// <summary>
/// 負(fù)責(zé)創(chuàng)建土豆肉絲這道菜
/// </summary>
/// <returns></returns>
public override Food CreateFoddFactory()
{
return new ShreddedPorkWithPotatoes();
}
}
/// <summary>
/// 客戶端調(diào)用
/// </summary>
class Client
{
static void Main(string[] args)
{
// 初始化做菜的兩個(gè)工廠()
Creator shreddedPorkWithPotatoesFactory = new ShreddedPorkWithPotatoesFactory();
Creator tomatoScrambledEggsFactory = new TomatoScrambledEggsFactory();
// 開(kāi)始做西紅柿炒蛋
Food tomatoScrambleEggs = tomatoScrambledEggsFactory.CreateFoddFactory();
tomatoScrambleEggs.Print();
//開(kāi)始做土豆肉絲
Food shreddedPorkWithPotatoes = shreddedPorkWithPotatoesFactory.CreateFoddFactory();
shreddedPorkWithPotatoes.Print();
Console.Read();
}
}
}
使用工廠方法實(shí)現(xiàn)的系統(tǒng),如果系統(tǒng)需要添加新產(chǎn)品時(shí),我們可以利用多態(tài)性來(lái)完成系統(tǒng)的擴(kuò)展,對(duì)于抽象工廠類(lèi)和具體工廠中的代碼都不需要做任何改動(dòng)。例如,我們我們還想點(diǎn)一個(gè)“肉末茄子”,此時(shí)我們只需要定義一個(gè)肉末茄子具體工廠類(lèi)和肉末茄子類(lèi)就可以。而不用像簡(jiǎn)單工廠模式中那樣去修改工廠類(lèi)中的實(shí)現(xiàn)(具體指添加case語(yǔ)句)。具體代碼為:
/// <summary>
/// 肉末茄子這道菜
/// </summary>
public class MincedMeatEggplant : Food
{
/// <summary>
/// 重寫(xiě)抽象類(lèi)中的方法
/// </summary>
public override void Print()
{
Console.WriteLine("肉末茄子好了");
}
}
/// <summary>
/// 肉末茄子工廠類(lèi),負(fù)責(zé)創(chuàng)建肉末茄子這道菜
/// </summary>
public class MincedMeatEggplantFactory : Creator
{
/// <summary>
/// 負(fù)責(zé)創(chuàng)建肉末茄子這道菜
/// </summary>
/// <returns></returns>
public override Food CreateFoddFactory()
{
return new MincedMeatEggplant();
}
}
/// <summary>
/// 客戶端調(diào)用
/// </summary>
class Client
{
static void Main(string[] args)
{
// 如果客戶又想點(diǎn)肉末茄子了
// 再另外初始化一個(gè)肉末茄子工廠
Creator minceMeatEggplantFactor = new MincedMeatEggplantFactory();
// 利用肉末茄子工廠來(lái)創(chuàng)建肉末茄子這道菜
Food minceMeatEggplant = minceMeatEggplantFactor.CreateFoddFactory();
minceMeatEggplant.Print();
Console.Read();
}
}
工廠方法模式的UML圖
講解完工廠模式的具體實(shí)現(xiàn)之后,讓我們看下工廠模式中各類(lèi)之間的UML圖:
從UML圖可以看出,在工廠方法模式中,工廠類(lèi)與具體產(chǎn)品類(lèi)具有平行的等級(jí)結(jié)構(gòu),它們之間是一一對(duì)應(yīng)的。針對(duì)UML圖的解釋如下:
Creator類(lèi):充當(dāng)抽象工廠角色,任何具體工廠都必須繼承該抽象類(lèi)
TomatoScrambledEggsFactory和ShreddedPorkWithPotatoesFactory類(lèi):充當(dāng)具體工廠角色,用來(lái)創(chuàng)建具體產(chǎn)品
Food類(lèi):充當(dāng)抽象產(chǎn)品角色,具體產(chǎn)品的抽象類(lèi)。任何具體產(chǎn)品都應(yīng)該繼承該類(lèi)
TomatoScrambledEggs和ShreddedPorkWithPotatoes類(lèi):充當(dāng)具體產(chǎn)品角色,實(shí)現(xiàn)抽象產(chǎn)品類(lèi)對(duì)定義的抽象方法,由具體工廠類(lèi)創(chuàng)建,它們之間有一一對(duì)應(yīng)的關(guān)系。
.NET中實(shí)現(xiàn)了工廠方法的類(lèi)
.NET 類(lèi)庫(kù)中也有很多實(shí)現(xiàn)了工廠方法的類(lèi),例如Asp.net中,處理程序?qū)ο笫蔷唧w用來(lái)處理請(qǐng)求,當(dāng)我們請(qǐng)求一個(gè)*.aspx的文件時(shí),此時(shí)會(huì)映射到System.Web.UI.PageHandlerFactory類(lèi)上進(jìn)行處理,而對(duì)*.ashx的請(qǐng)求將映射到System.Web.UI.SimpleHandlerFactory類(lèi)中(這兩個(gè)類(lèi)都是繼承于IHttpHandlerFactory接口的),關(guān)于這點(diǎn)說(shuō)明我們可以在“C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\Web.Config”文件中找到相關(guān)定義,具體定義如下:
<httpHandlers>
<add path="*.axd" verb="*" type="System.Web.HttpNotFoundHandler" validate="True" />
<add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True" />
<add path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" validate="True" />
</httpHandlers>
下面我們就具體看下工廠方法模式在Asp.net中是如何實(shí)現(xiàn)的,如果對(duì)一個(gè)Index.aspx頁(yè)面發(fā)出請(qǐng)求時(shí),將會(huì)調(diào)用PageHandlerFactory中GetHandler方法來(lái)創(chuàng)建一個(gè)Index.aspx對(duì)象,它們之間的類(lèi)圖關(guān)系如下:
總結(jié)
工廠方法模式通過(guò)面向?qū)ο缶幊讨械亩鄳B(tài)性來(lái)將對(duì)象的創(chuàng)建延遲到具體工廠中,從而解決了簡(jiǎn)單工廠模式中存在的問(wèn)題,也很好地符合了開(kāi)放封閉原則(即對(duì)擴(kuò)展開(kāi)發(fā),對(duì)修改封閉)。
上一篇:解析C#設(shè)計(jì)模式編程中外觀模式Facade Pattern的應(yīng)用
欄 目:C#教程
本文標(biāo)題:使用設(shè)計(jì)模式中的工廠方法模式進(jìn)行C#編程的示例講解
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/6683.html
您可能感興趣的文章
- 01-10C#使用Dispose模式實(shí)現(xiàn)手動(dòng)對(duì)資源的釋放
- 01-10C#3.0使用EventLog類(lèi)寫(xiě)Windows事件日志的方法
- 01-10C#使用windows服務(wù)開(kāi)啟應(yīng)用程序的方法
- 01-10深入淺出23種設(shè)計(jì)模式
- 01-10c# ArrayList的使用方法小總結(jié)
- 01-10C#中查找Dictionary中的重復(fù)值的方法
- 01-10C#使用ADO.Net部件來(lái)訪問(wèn)Access數(shù)據(jù)庫(kù)的方法
- 01-10C#使用Mutex簡(jiǎn)單實(shí)現(xiàn)程序單實(shí)例運(yùn)行的方法
- 01-10使用Nopcommerce為商城添加滿XX減XX優(yōu)惠券功能
- 01-10C#將圖片存放到SQL SERVER數(shù)據(jù)庫(kù)中的方法


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開(kāi)的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫(xiě)Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10delphi制作wav文件的方法
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-10C#中split用法實(shí)例總結(jié)


