![C#23種設(shè)計(jì)模式 第4章 工廠方法_第1頁(yè)](http://file4.renrendoc.com/view/ad1714f2288cba49652f61fb25606381/ad1714f2288cba49652f61fb256063811.gif)
![C#23種設(shè)計(jì)模式 第4章 工廠方法_第2頁(yè)](http://file4.renrendoc.com/view/ad1714f2288cba49652f61fb25606381/ad1714f2288cba49652f61fb256063812.gif)
![C#23種設(shè)計(jì)模式 第4章 工廠方法_第3頁(yè)](http://file4.renrendoc.com/view/ad1714f2288cba49652f61fb25606381/ad1714f2288cba49652f61fb256063813.gif)
![C#23種設(shè)計(jì)模式 第4章 工廠方法_第4頁(yè)](http://file4.renrendoc.com/view/ad1714f2288cba49652f61fb25606381/ad1714f2288cba49652f61fb256063814.gif)
![C#23種設(shè)計(jì)模式 第4章 工廠方法_第5頁(yè)](http://file4.renrendoc.com/view/ad1714f2288cba49652f61fb25606381/ad1714f2288cba49652f61fb256063815.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
NET設(shè)計(jì)模式(5):工廠方法模式(FactoryMethod)工廠方法模式(FactoryMethod).NET設(shè)計(jì)模式系列之五Terrylee,2004年1月2日概述在軟件系統(tǒng)中,經(jīng)常面臨著“某個(gè)對(duì)象”的創(chuàng)建工作,由于需求的變化,這個(gè)對(duì)象的具體實(shí)現(xiàn)經(jīng)常面臨著劇烈的變化,但是它卻擁有比較穩(wěn)定的接口。如何應(yīng)對(duì)這種變化?提供一種封裝機(jī)制來(lái)隔離出“這個(gè)易變對(duì)象”的變化,從而保持系統(tǒng)中“其它依賴該對(duì)象的對(duì)象”不隨著需求的改變而改變?這就是要說(shuō)的FactoryMethod模式了。意圖定義一個(gè)用戶創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪一個(gè)類。FactoryMethod使一個(gè)類的實(shí)例化延遲到其子類。結(jié)構(gòu)圖生活中的例子工廠方法定義一個(gè)用于創(chuàng)建對(duì)象的接口,但是讓子類決定實(shí)例化哪個(gè)類。壓注成型演示了這種模式。塑料玩具制造商加工塑料粉,將塑料注入到希望形狀的模具中。玩具的類別(車,人物等等)是由模具決定的。玩具馬模具工廠方法解說(shuō)在工廠方法模式中,核心的工廠類不再負(fù)責(zé)所有產(chǎn)品的創(chuàng)建,而是將具體創(chuàng)建工作交給子類去做。這個(gè)核心類僅僅負(fù)責(zé)給出具體工廠必須實(shí)現(xiàn)的接口,而不接觸哪一個(gè)產(chǎn)品類被實(shí)例化這種細(xì)節(jié)。這使得工廠方法模式可以允許系統(tǒng)在不修改工廠角色的情況下引進(jìn)新產(chǎn)品。在FactoryMethod模式中,工廠類與產(chǎn)品類往往具有平行的等級(jí)結(jié)構(gòu),它們之間一一對(duì)應(yīng)?,F(xiàn)在我們考慮一個(gè)日志記錄的例子(這里我們只是為了說(shuō)明FactoryMethod模式,實(shí)際項(xiàng)目中的日志記錄不會(huì)這么去做,也要比這復(fù)雜一些)。假定我們要設(shè)計(jì)日志記錄的類,支持記錄的方法有FileLog和EventLog兩種方式。在這里我們先不談設(shè)計(jì)模式,那么這個(gè)日志記錄的類就很好實(shí)現(xiàn)了:日田///<summary>1///日志記錄類L///</summary>publicclassLog5日田{6IpublicvoidWriteEvent()8白由{IConsole.WriteLine("EventLogSuccess!");10卜}11IpublicvoidWriteFile()13白由{14IConsole.WriteLine("FileLogSuccess!");15卜}1617IpublicvoidWrite(stringLogType)18白由{19Iswitch(LogType.ToLower())20白由{211case"event":IWriteEvent();Ibreak;24Icase"file":WriteFile();271break;28291default:301break;31卜}I-}}34這樣的程序結(jié)構(gòu)顯然不能符合我們的要求,如果我們?cè)黾右环N新的日志記錄的方式DatabaseLog,那就要修改Log類,隨著記錄方式的變化,switch語(yǔ)句在不斷的變化,這樣就引起了整個(gè)應(yīng)用程序的不穩(wěn)定,進(jìn)一步分析上面的代碼,發(fā)現(xiàn)對(duì)于EventLog和FileLog是兩種完全不同的記錄方式,它們之間不應(yīng)該存在必然的聯(lián)系,而應(yīng)該把它們分別作為單獨(dú)的對(duì)象來(lái)對(duì)待。日田///<summary>I///EventLog類L///</summary>publicclassEventLog5日田{IpublicvoidWrite()7白由{IConsole.WriteLine("EventLogWriteSuccess!");}}12日田///<summary>I///FileLog類L///</summary>publicclassFileLog16日田{17IpublicvoidWrite()18白中{19IConsole.WriteLine("FileLogWriteSuccess!");201-}21}22步抽象,為它們抽象出一個(gè)共同的父類,結(jié)構(gòu)圖如下:實(shí)現(xiàn)代碼:日田///<summary>I///Log類I//</summary>publicabstractclassLog5日田{publicabstractvoidWrite();}8此時(shí)EventLog和FileLog類的代碼應(yīng)該如下:日田///<summary>I///EventLog類L///</summary>publicclassEventLog:Log5日田{6IpublicoverridevoidWrite()7白由{IConsole.WriteLine("EventLogWriteSuccess!");}}日田///<summary>I///FileLog類L///</summary>publicclassFileLog:Log15日田{IpublicoverridevoidWrite()17白由{18IConsole.WriteLine("FileLogWriteSuccess!");19卜}20}21此時(shí)我們?cè)倏丛黾有碌挠涗浫罩痉绞紻atabaseLog的時(shí)候,需要做哪些事情?只需要增加一個(gè)繼承父類Log的子類來(lái)實(shí)現(xiàn),而無(wú)需再去修改EventLog和FileLog類,這樣的設(shè)計(jì)滿足了類之間的層次關(guān)系,又很好的符合了面向?qū)ο笤O(shè)計(jì)中的單一職責(zé)原則,每一個(gè)類都只負(fù)責(zé)一件具體的事情。到這里似乎我們的設(shè)計(jì)很完美了,事實(shí)上我們還沒有看客戶程序如何去調(diào)用。在應(yīng)用程序中,我們要使用某一種日志記錄方式,也許會(huì)用到如下這樣的語(yǔ)句:EventLogeventlog=newEventLog();eventlog.Write();當(dāng)日志記錄的方式從EventLog變化為FileLog,我們就得修改所有程序代碼中出現(xiàn)上面語(yǔ)句的部分,這樣的工作量是可想而知的。此時(shí)就需要解耦具體的日志記錄方式和應(yīng)用程序。這就要引入FactoryMethod模式了,每一個(gè)日志記錄的對(duì)象就是工廠所生成的產(chǎn)品,既然有兩種記錄方式,那就需要兩個(gè)不同的工廠去生產(chǎn)了,代碼如下:日田///<summary>I///EventFactory類L///</summary>publicclassEventFactory5日田{6IpublicEventLogCreate()7白由{IreturnnewEventLog();}}日田///<summary>I///FileFactory類L///</summary>publicclassFileFactory16IpublicFileLogCreate()17白中{18IreturnnewFileLog();19卜}20}21這兩個(gè)工廠和具體的產(chǎn)品之間是平行的結(jié)構(gòu),并一一對(duì)應(yīng),并在它們的基礎(chǔ)上抽象出一個(gè)公用的接口,結(jié)構(gòu)圖如下:實(shí)現(xiàn)代碼如下:日田///<summary>I///LogFactory類L///</summary>publicabstractclassLogFactory5日田{publicabstractLogCreate();}此時(shí)兩個(gè)具體工廠的代碼應(yīng)該如下:日田///<summary>I///EventFactory類L///</summary>publicclassEventFactory:LogFactory6IpublicoverrideEventLogCreate()7白中{IreturnnewEventLog();}}日田///<summary>I///FileFactory類L///</summary>publicclassFileFactory:LogFactory15日田{16IpublicoverrideFileLogCreate()17白由{18IreturnnewFileLog();19卜}20}21這樣通過(guò)工廠方法模式我們把上面那對(duì)象創(chuàng)建工作封裝在了工廠中,此時(shí)我們似乎完成了整個(gè)FactoryMethod的過(guò)程。這樣達(dá)到了我們應(yīng)用程序和具體日志記錄對(duì)象之間解耦的目的了嗎?看一下此時(shí)客戶端程序代碼:日田///<summary>I///App類L///</summary>publicclassApp5日田{6IpublicstaticvoidMain(string[]args)7白由{8ILogFactoryfactory=newEventFactory();9ILoglog=factory.Create();11121log.Write();13卜}14}15在客戶程序中,我們有效地避免了具體產(chǎn)品對(duì)象和應(yīng)用程序之間的耦合,可是我們也看到,增加了具體工廠對(duì)象和應(yīng)用程序之間的耦合。那這樣究竟帶來(lái)什么好處呢?我們知道,在應(yīng)用程序中,Log對(duì)象的創(chuàng)建是頻繁的,在這里我們可以把LogFactoryfactory=newEventFactory();這句話放在一個(gè)類模塊中,任何需要用到Log對(duì)象的地方仍然不變。要是換一種日志記錄方式,只要修改一處為:LogFactoryfactory=newFileFactory();其余的任何地方我們都不需要去修改。有人會(huì)說(shuō)那還是修改代碼,其實(shí)在開發(fā)中我們很難避免修改,但是我們可以盡量做到只修改一處。其實(shí)利用.NET的特性,我們可以避免這種不必要的修改。下面我們利用.NET中的反射機(jī)制來(lái)進(jìn)一步修改我們的程序,這時(shí)就要用到配置文件了,如果我們想使用哪一種日志記錄方式,則在相應(yīng)的配置文件中設(shè)置如下:<appSettings><addkey="factoryName"value="EventFactory"></add></appSettings>4此時(shí)客戶端代碼如下:日田///<summary>I///App類L///</summary>publicclassApp5日田{6IpublicstaticvoidMain(string[]args)7白由{8IstringstrfactoryName=ConfigurationSettings.AppSettings["factoryName"];9ILogFactoryfactory;Ifactory=(LogFactory)Assembly.Load("FactoryMethod").CreateInstance("FactoryMethod."+strfactoryName);1213ILoglog=factory.Create();141log.Write();I"}}17現(xiàn)在我們看到,在引進(jìn)新產(chǎn)品(日志記錄方式)的情況下,我們并不需要去修改工廠類,而只是增加新的產(chǎn)品類和新的工廠類(注意:這是任何時(shí)候都不能避免的),這樣很好的符合了開放封閉原則。ASP.NETHTTP通道中的應(yīng)用FactoryMethod模式在ASP.NETHTTP通道中我們可以找到很多的例子。ASP.NETHTTP通道是System.Web命名空間下的一個(gè)類,WEBServer使用該類處理接收到的HTTP請(qǐng)求,并給客戶端發(fā)送響應(yīng)。HTTP通道主要的工作有Session管理,應(yīng)用程序池管理,緩存管理,安全等。System.Web.HttpApplicationFactoryHttpRuntime是HTTP通道的入口點(diǎn),它根據(jù)每一個(gè)具體的請(qǐng)求創(chuàng)建一個(gè)HttpContext實(shí)例,HttpRuntime并沒有確定它將要處理請(qǐng)求的HttpApplication對(duì)象的類型,它調(diào)用了一個(gè)靜態(tài)的工廠方法HttpApplicationFactory.GetApplicationInstance,通過(guò)它來(lái)創(chuàng)建HttpContext實(shí)例。GetApplicationInstance使用HttpContext實(shí)例來(lái)確定針對(duì)這個(gè)請(qǐng)求該響應(yīng)哪個(gè)虛擬路徑,如果這個(gè)虛擬路徑以前請(qǐng)求過(guò),HttpApplication(或者一個(gè)繼承于ASP.Global_asax的類的實(shí)例)將直接從應(yīng)用程序池中返回,否則針對(duì)該虛擬路徑將創(chuàng)建一個(gè)新的HttpApplication對(duì)象并返回。如下圖所示:HttpApplicationFactory.GetApplicationInstance帶有^個(gè)類型為HttpContext的參數(shù),創(chuàng)建的所有對(duì)象(產(chǎn)品)都是HttpApplication的類型,通過(guò)反編譯,來(lái)看一下GetApplicationInstance的實(shí)現(xiàn):1internalstaticIHttpHandlerGetApplicationInstance(HttpContextcontext)2曰田{if(HttpApplicationFactory._customApplication!=HttpApplicationFactory.GetApplicationInstance帶有^個(gè)類型為HttpContext的參數(shù),創(chuàng)建的所有對(duì)象(產(chǎn)品)都是HttpApplication的類型,通過(guò)反編譯,來(lái)看一下GetApplicationInstance的實(shí)現(xiàn):1internalstaticIHttpHandlerGetApplicationInstance(HttpContextcontext)2曰田{if(HttpApplicationFactory._customApplication!=null)returnHttpApplicationFactory._customApplication;if(HttpDebugHandler.IsDebuggingRequest(context))8百中returnnewHttpDebugHandler();1011if(!HttpApplicationFactory._theApplicationFactory._inited)13lock(HttpApplicationFactory._theApplicationFactory)14攤15if(!HttpApplicationFactory._theApplicationFactory._inited)16白由17HttpApplicationFactory._theApplicationFactory.Init(context);15171HttpApplicationFactory._theApplicationFactory._inited=true;TOC\o"1-5"\h\z}}}IreturnHttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(context);L}24System.Web.IHttpHandlerFactory我們來(lái)做進(jìn)一步的探索,HttpApplication實(shí)例需要一個(gè)Handler對(duì)象來(lái)處理資源請(qǐng)求,HttpApplication的主要任務(wù)就是找到真正處理請(qǐng)求的類。HttpApplication首先確定了一個(gè)創(chuàng)建Handler對(duì)象的工廠,來(lái)看一下在Machine.config文件中的配置區(qū)<httphandlers>,在配置文件注冊(cè)了應(yīng)用程序的具體處理類。例如在Machine.config中對(duì)火.aspx的處理將映射到USystem.Web.UI.PageHandlerFactory類,而對(duì)火.ashx的處理將映射到USystem.Web.UI.SimpleHandlerFactory類,這兩個(gè)類都是繼承于IhttpHandlerFactory接口的具體類:<httpHandlers><addverb="火"path="火.aspx"type="System.Web.UI.PageHandlerFactory"/><addverb="火"path="火.ashx"type="System.Web.UI.SimpleHandlerFactory"/>這個(gè)配置區(qū)建立了資源請(qǐng)求的類型和處理請(qǐng)求的類之間的一個(gè)映射集。如果一個(gè).aspx頁(yè)面發(fā)出了請(qǐng)求,將會(huì)調(diào)用System.Web.UI.PageHandlerFactory類,HttpApplication調(diào)用接口IHttpHandlerFactory中的工廠方法GetHandler來(lái)創(chuàng)建一■個(gè)Handler對(duì)象。當(dāng)一'個(gè)名為sample.aspx的頁(yè)面發(fā)出請(qǐng)求時(shí),通過(guò)PageHandlerFactory將返回一■個(gè)ASP.SamplePage_aspx對(duì)象(具體產(chǎn)品),如下圖:IHttpHandlerFactory工廠:1publicinterfaceIHttpHandlerFactory2日田{//MethodsIHttpHandlerGetHandler(HttpContextcontext,stringrequestType,stringurl,stringpathTranslated);voidReleaseHandler(IHttpHandlerhandler);L}7IHttpHandlerFactory.GetHandler是一個(gè)工廠方法模式的典型例子,在這個(gè)應(yīng)用中,各個(gè)角色的設(shè)置如下:抽象工廠角色:IHttpHandlerFactory具體工廠角色:PageHandlerFactory具體產(chǎn)品角色:ASP.SamplePage_aspx進(jìn)一步去理解理解上面所說(shuō)的之后,我們就可以去自定義工廠類來(lái)對(duì)特定的資源類型進(jìn)行處理。第一步我們需要?jiǎng)?chuàng)建兩個(gè)類去分別實(shí)現(xiàn)IHttpHandlerFactory和IHttpHandler這兩個(gè)接口。1publicclassHttpHandlerFactoryImpl:IHttpHandlerFactory(2IHttpHandlerIHttpHandlerFactory.GetHandler(HttpContextcontext,StringrequestType,由由Stringurl,StringpathTranslated)(6returnnewHttpHandlerImpl();89}//IHttpHandlerFactory.GetHandler10voidIHttpHandlerFactory.ReleaseHandler(白由IHttpHandlerhandler)(/*no-op*/}13L14}//HttpHandlerFactoryImpl1516publicclassHttpHandlerImpl:IHttpHandler(1718白由voidIHttpHandler.ProcessRequest(HttpContextcontext)(1920context.Response.Write("samplehandlerinvoked'”");2122}//ProcessRequest2324白由boolIHttpHandler.IsReusable(get(returnfalse;}}25L26}//HttpHandlerlmpl27第二步需要在配置文件中建立資源請(qǐng)求類型和處理程序之間的映射。我們希望當(dāng)請(qǐng)求的類型為*.sample時(shí)進(jìn)入我們自定義的處理程序,如下:<httpHandlers><addverb="火"path="火.sample"type="HttpHandlerFactoryImpl,SampleHandler"/></httpHandlers>最后一步我們需要把文件擴(kuò)展*.sample映射至UASP.NETISAPI擴(kuò)展DLL(aspnet_isapi.dll)上。由于我們已經(jīng)建立了用于處理新擴(kuò)展文件的處理程序了,我們還需要把這個(gè)擴(kuò)展名告訴IIS并把它映射到ASP.NET。如果你不執(zhí)行這個(gè)步驟而試圖訪問(wèn)火.sample文件,IIS將簡(jiǎn)單地返回該文件而不是把它傳遞給ASP.NET運(yùn)行時(shí)。其結(jié)果是該HTTP處理程序不會(huì)被調(diào)用。運(yùn)行Internet服務(wù)管理器,右鍵點(diǎn)擊默認(rèn)Web站點(diǎn),選擇屬性,移動(dòng)到主目錄選項(xiàng)頁(yè),并點(diǎn)擊配置按鈕。應(yīng)用程序配置對(duì)話框彈出來(lái)了。點(diǎn)擊添加按鈕并在可執(zhí)行字段輸入aspnet_isapi.dll文件路徑,在擴(kuò)展字段輸入.sample。其它字段不用處理;該對(duì)話框如下所示:在.NETFramework中,關(guān)于工廠模式的使用有很多的例子,例如【Enumerable和lEnumerator就是一個(gè)Creator和一個(gè)Product;System.Security.Cryptography中關(guān)于加密算法的選擇,S
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 班級(jí)自我管理提升計(jì)劃
- 急診安全文化建設(shè)實(shí)踐計(jì)劃
- 實(shí)驗(yàn)室安全規(guī)范與培訓(xùn)計(jì)劃
- 學(xué)校教學(xué)活動(dòng)安排計(jì)劃
- 秘書在團(tuán)隊(duì)溝通中的角色計(jì)劃
- 小班三維課程與教育理念實(shí)踐計(jì)劃
- 2025年美司那項(xiàng)目建議書
- 2025年中國(guó)異構(gòu)計(jì)算行業(yè)市場(chǎng)運(yùn)行態(tài)勢(shì)及發(fā)展趨勢(shì)預(yù)測(cè)報(bào)告-智研咨詢發(fā)布
- 2025年多通道腦電圖機(jī)項(xiàng)目建議書
- 淮安市2024-2025學(xué)年上學(xué)期高一期末考試地理試題(含答案)
- DB32-T 3129-2016適合機(jī)械化作業(yè)的單體鋼架塑料大棚 技術(shù)規(guī)范-(高清現(xiàn)行)
- 《花婆婆》兒童繪本故事
- DB44∕T 2149-2018 森林資源規(guī)劃設(shè)計(jì)調(diào)查技術(shù)規(guī)程
- 數(shù)據(jù)結(jié)構(gòu)英文教學(xué)課件:chapter10 Hashing
- 藍(lán)色卡通風(fēng)學(xué)生班干部競(jìng)選介紹PPT模板課件
- 人教新目標(biāo)英語(yǔ)九年級(jí)上冊(cè)單詞中文Units
- 機(jī)動(dòng)車牌證申請(qǐng)表格模板(完整版)
- 《國(guó)家電網(wǎng)公司十八項(xiàng)電網(wǎng)反事故措施(試行)》實(shí)施細(xì)則
- 鋼絲網(wǎng)架珍珠巖夾心板安裝方法
- 工藝管廊架施工方案
- 六宮格數(shù)獨(dú)解題技巧
評(píng)論
0/150
提交評(píng)論