


版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、 NET(C#) In ternals: .NET Framework中已使用的設(shè)計(jì)模式2010-05-2920:01by 吳秦,2234visits, 網(wǎng)摘,收藏,編輯適合有一定設(shè)計(jì)模式基礎(chǔ)和.NET基礎(chǔ)的人閱讀寫(xiě)在前面“設(shè)計(jì)模式”我一向是敬而遠(yuǎn)之的態(tài)度, 不會(huì)去寫(xiě)這方面的文章,原因有二:第 一,要想寫(xiě)好設(shè)計(jì)模式的文章太難,需要筆者豐富的經(jīng)驗(yàn);第二,沒(méi)有深厚的功 底寫(xiě)出的設(shè)計(jì)模式文章容易誤導(dǎo)他人。 自認(rèn)沒(méi)有深厚的功底,但我不會(huì)為了設(shè)計(jì) 模式而設(shè)計(jì)模式。我想大部分人對(duì)設(shè)計(jì)模式的理解是不夠深刻的, 不然應(yīng)用自如, 特別是初學(xué)者!所有研究高質(zhì)量的源碼或框架是我們學(xué)習(xí)實(shí)踐設(shè)計(jì)模式的好途徑 之一。而我
2、之所以寫(xiě)這篇文章,主要是因?yàn)樗鼜?NETFramework入手介紹已經(jīng)使用的設(shè) 計(jì)模式,作為一個(gè).NET開(kāi)發(fā)人員應(yīng)該再熟悉不過(guò)了,能夠有比較深刻的認(rèn)識(shí)和 理解。本文從.NETFramework中入手,發(fā)掘在.NETFramework中如何使用設(shè)計(jì)模 式的。從中我們知道我們平時(shí)使用.NET時(shí),我們使用了那些模式及學(xué)習(xí)使用設(shè) 計(jì)模式。本文意譯自 Discover the Desig n Patter ns You're Already Us ing in the .NET Framework及加入了相關(guān)設(shè)計(jì)模式的 UML表示和主要介紹。主要內(nèi)容如下:* .NETFramework中使用的觀
3、察者模式(ObserverPattern )* .NETFramework中使用的迭代器模式(IteratorPattern* .NETFramework中使用的裝飾模式(DecoratorPattern )« .NETFramework中使用的適配器模式(AdapterPattern .NETFramework中使用的工廠模式(FactoryPattern ) .NETFramework中使用的策略模式(StrategyPattern ) ASP.NET中的組合模式(CompositePattern .NETFramework中使用的模板方法模式(TemplateMethodPat
4、tern ) ASP.NET管道中的模式(PatternsintheASP.NETPipelineo 截取過(guò)濾器模式(InterceptingFilterPatterno 頁(yè)面控制器模式(PageControllerPatterno ASP.NET中的其它web表示模式(OtherWebPresentationPatternsinASP.NET )*總結(jié)觀察者模式:在此種模式中,一個(gè)目標(biāo)物件管理所有相依于它的觀察者物件, 并 且在它本身的狀態(tài)改變時(shí)主動(dòng)發(fā)出通知。這通常通過(guò)調(diào)用各觀察者所提供的方法 來(lái)實(shí)現(xiàn)。它的UML表示如下:圖1、觀察者模式的UML表示(來(lái)源:維基百科)好的面向?qū)ο笤O(shè)計(jì)都強(qiáng)調(diào)
5、圭寸裝(encapsulation )和松耦合(loosecoupling )。 換句話說(shuō),類應(yīng)該保持內(nèi)部細(xì)節(jié)私有并且最小化類之間嚴(yán)格的依賴關(guān)系。大部分應(yīng)用程序,類并不是獨(dú)立工作的,而是與其他類交互的。類交互的一個(gè)通常例子 是:一個(gè)類應(yīng)該(觀察者,Observer)被通知,當(dāng)被觀察者(Subject )的某些 東西改變了。例如,當(dāng)單擊一個(gè)按鈕后可能某些Win dowsForms的控件需要更新他們的顯示。一個(gè)簡(jiǎn)單的解決方案是,當(dāng)狀態(tài)改變時(shí)讓被觀察者調(diào)用觀察者特定 的方法。但是,這回引入一連串的問(wèn)題。因?yàn)楸挥^察者需要知道調(diào)用哪個(gè)方法, 這樣就與特定觀察者產(chǎn)生了緊耦合(tightcoupli ng
6、)。而且,如果當(dāng)需要添加 多個(gè)觀察者時(shí),不得不繼續(xù)添加每個(gè)觀察者方法調(diào)用的代碼。如果觀察者的數(shù)量動(dòng)態(tài)地改變,這將變得更復(fù)雜。這將很難維護(hù)!應(yīng)用觀察者模式能有效地解決這個(gè)問(wèn)題??梢詮挠^察者解耦被觀察者,因此在設(shè) 計(jì)時(shí)和運(yùn)行時(shí)觀察者可以容易地添加和移除。被觀察者維護(hù)者一個(gè)對(duì)它感興趣的 觀察者列表,每次被觀察者的狀態(tài)改變時(shí),它對(duì)每個(gè)觀察者調(diào)用Notify方法。下面這段代碼展示了一個(gè)實(shí)現(xiàn)示例:view source print?publicabstractclassCa noni calSubjectBase03040506070809101112131415161718privateArrayLis
7、t_observers=newArrayList(); publicvoidAdd(ICanonicalObservero)_observers.Add(o);publicvoidRemove(ICanonicalObservero)_observers.Remove(o);publicvoidNotify()foreach(ICanonicalObserveroin_observers)o.Notify();19 20voidNotify3 ();所有的觀察者類實(shí)現(xiàn)ICanonicalObserver接口,所有的被觀察者必須繼承自 CanonicalSubjectBase。如果一個(gè)新的觀察者
8、想監(jiān)視被觀察者,Add方法可以輕松的處理而不必改變被觀察者類的代碼。注意:每個(gè)被觀察者僅僅直接依賴于ICa non icalObserver接口,而不是特定的觀察者。然而使用GOF勺觀察者模式解決這些問(wèn)題仍有一些障礙,因?yàn)楸挥^察者必須繼承 一個(gè)特定的基類且觀察者必須實(shí)現(xiàn)一個(gè)特定接口??紤]回Win dowsForms按鈕的例子,.NETFramework引入了委托和事件來(lái)解決這些問(wèn)題。如果你已經(jīng)編寫(xiě)過(guò) ASP.NET或WindowsForms程序,你可能就是有了事件和事件處理器。事件作為 被觀察者,然而委托作為觀察者。下面代碼展示了使用事件的觀察者模式:view source print?pub
9、licdelegatevoidEve nt1Ha nder();publicdelegatevoidEve nt2Ha ndler(i nta);publicclassSubject06 )07 1;08 2;09 ()1011 en t1;12publicSubject(publicEve nt1Ha nderEve ntpublicEve nt2Ha ndlerEve nt publicvoidRaiseEve nt1Eve nt1Ha ndlerev=Evif(ev!=null)ev();131415161718192021222324252627282930313publicvoidR
10、aiseEvent2()Event2Handlerev=Event2;if(ev!=null)ev(6)publicclassObserver1publicObserver1(Subjects)s.Event1+=newEvent1Hander(HandleEves.Event2+=newEvent2Handler(HandleEvent1);nt2);publicvoidHandleEvent1()233 )3435 2");3637 publicvoidHa ndleEve nt2(i ntaCon sole.WriteLi ne("Observer1-Eve ntWi
11、ndowsFormsButton控件公開(kāi)一個(gè) Click事件,當(dāng)button被點(diǎn)擊時(shí)產(chǎn)生。任何 設(shè)計(jì)為響應(yīng)這個(gè)事件的類僅需要用這個(gè)事件注冊(cè)一個(gè)委托。Butt on類不依賴與任何潛在的觀察者,并且每個(gè)觀察者僅需要知道這個(gè)事件的委托的正確類型(這里是EventHandler )。因?yàn)镋ventHandler是一個(gè)委托類型而不是一個(gè)接口,每 個(gè)觀察者不需要實(shí)現(xiàn)一個(gè)額外的接口。假定它已經(jīng)包含一個(gè)與簽名兼容的方法, 只需要用被觀察者的事件注冊(cè)方法。通過(guò)使用委托和事件,觀察者模式使被觀察 者與觀察者們之間解耦了。2、迭代器模式(IteratorPattern)迭代器模式:它可以讓使用者通過(guò)特定的接口巡訪容
12、器中的每一個(gè)元素而不用了 解底層的實(shí)作。它的UML表示如下:圖2、迭代器模式的UML表示(來(lái)源:TerryLee的.NET設(shè)計(jì)模式(18):迭代器模式(Iterator Pattern)許多編程任務(wù)包括操作對(duì)象的集合。不管這些集合是簡(jiǎn)單的列表還是更復(fù)雜的, 如二叉樹(shù),經(jīng)常需要訪問(wèn)集合中的每個(gè)對(duì)象。事實(shí)上,根據(jù)集合可能有幾種不同 的訪問(wèn)每個(gè)對(duì)象的方法,諸如從前向后、從后向前、前序或后序。為了保持集合 簡(jiǎn)單,遍歷代碼通常放在自己?jiǎn)为?dú)的類中。存儲(chǔ)一個(gè)對(duì)象列表的常用方法之一就是用數(shù)組。數(shù)組類型在VisualBasic.NET和C艸都是內(nèi)置類型,他們都有一個(gè)循環(huán)結(jié)構(gòu)用于在數(shù)組上迭代:foreach (C
13、#) 和ForEach(VisualBasic.NET )。下面是一個(gè)在數(shù)組上進(jìn)行迭代的簡(jiǎn)單例子:view sourceprint?1 in tvalues=newin t1,2,3,4,5;22 foreach(i nti inv alues)3 _Co nsole.Write(i.ToStri ng()+"")5j4 這些語(yǔ)句在后臺(tái)對(duì)數(shù)組使用了迭代器。我們需要知道的就是它保證了循環(huán)保證了對(duì)數(shù)組中的每個(gè)元素進(jìn)行一次遍歷。為了使這些語(yǔ)句起作用,foreach表達(dá)式中涉及的對(duì)象必須實(shí)現(xiàn)了IEnumerable接口。任何實(shí)現(xiàn)了 lEnumerable接口的對(duì)象集合都可以被遍歷(
14、枚舉)。這個(gè)接 口僅有一個(gè)方法GetEnumerator(),它返回一個(gè)實(shí)現(xiàn)了 lEnumerable的對(duì)象。lEnumerator接口包含遍歷迭代集合所需要的代碼,它有一個(gè)屬性Current標(biāo)識(shí)當(dāng)前對(duì)象、方法MoveNext()移到下一個(gè)對(duì)象、方法 Reset()重新開(kāi)始。System.Collections 命名空間中所有的集合類,及數(shù)組,都實(shí)現(xiàn)了 IEnumerable 接口,因此能被迭代。如果你測(cè)試了由C#編譯器生成foreach的MSIL代碼,你可以看到大部分情況它 僅使用IEnumerator去做迭代(特定類型,如數(shù)組和字符串,由編譯器特別處理)。 下面代碼展示用IEnumerat
15、or方法實(shí)現(xiàn)上例功能的代碼:view sourceprint?1 in tvalues=newin t1,2,3,4,5;2 IEnu meratore=(IE nu merable)values).GetE nu merator();3 while(e.MoveNext()4 Co nsole.Write(e.Curre nt.ToStri ng()+"").NETFramework使用IEnumerable和IEnumerator接口實(shí)現(xiàn)了迭代器模式。迭代 器模式使我們能夠輕松地遍歷一個(gè)集合而不用了解集合內(nèi)部的工作機(jī)制。一個(gè)迭代器類,實(shí)現(xiàn)了 IEnumerator接口,
16、是一個(gè)獨(dú)立與集合的類,實(shí)現(xiàn)了 IEnumerable接口。迭代器類維護(hù)遍歷的狀態(tài)(包括當(dāng)前元素是哪個(gè)和是否有更 多的元素要遍歷)。這個(gè)遍歷的算法也包含在迭代器類中。這種方法可以同時(shí)有幾個(gè)迭代器,每個(gè)以不同的方式遍歷同一個(gè)集合,而不會(huì)對(duì)集合類增加任何復(fù)雜。3、裝飾模式(DecoratorPattern )裝飾模式:一種動(dòng)態(tài)地往一個(gè)類中添加新的行為的設(shè)計(jì)模式, 通過(guò)使用修飾模式, 可以在運(yùn)行時(shí)擴(kuò)充一個(gè)類的功能。原理是:增加一個(gè)修飾類包裹原來(lái)的類,包裹 的方式一般是通過(guò)在將原來(lái)的對(duì)象作為修飾類的構(gòu)造函數(shù)的參數(shù)。裝飾類實(shí)現(xiàn)新的功能,但是,在不需要用到新功能的地方,它可以直接調(diào)用原來(lái)的類中的方法。 修飾
17、類必須和原來(lái)的類有相同的接口。UML表示如下:ba&a.Operatlofi(t圖3、裝飾模式UML表示(來(lái)源:TerryLee 的.NET 設(shè)計(jì)模式(10):裝飾模式(Decorator Pattern)任何有用的可執(zhí)行程序包括讀取輸入或?qū)戄敵觯?或者都有。盡管數(shù)據(jù)源被讀或?qū)懀?能夠把它們抽象地看成字節(jié)序列。.NET使用類去表示這個(gè)抽 象。不管這些數(shù)據(jù)是包含在文本文件中字符,還是 TCP/IP網(wǎng)絡(luò)流的數(shù)據(jù),或任 何其他實(shí)體中,你將通過(guò)一個(gè) Stream訪問(wèn)它們。因?yàn)橛糜谖募?shù)據(jù)的類(FileStream )和用于網(wǎng)絡(luò)流的類(NetWorkStream)都繼承自Stream,你可以 簡(jiǎn)
18、單地編寫(xiě)?yīng)毩⒂跀?shù)據(jù)源的代碼處理數(shù)據(jù)。下面的代碼展示從一個(gè)Stream中打印字節(jié)到控制臺(tái):view source print?1 publicstaticvoidPri ntBytes(Streams)2 34in tb;while(b=fs.ReadByte()>=0)56 +"");Con sole.Write(b7每次讀取單個(gè)字節(jié)通常不是最高效的訪問(wèn)流的方法。例如,硬件驅(qū)動(dòng)器有能力(且 優(yōu)化了)從磁盤(pán)的一大塊中讀取連續(xù)的數(shù)據(jù)塊。如果你知道你將讀取幾個(gè)字符, 最好一次從磁盤(pán)中讀取一個(gè)塊然后從內(nèi)存中逐字節(jié)地使用??蚣馨˙ufferedStream類就是做這個(gè)的。Bu
19、fferedStream的構(gòu)造函數(shù)以流的類型為參 數(shù),設(shè)定你想緩存訪問(wèn)的類型。BufferedStream重寫(xiě)了 Stream的主要方法,諸 如Read和Write,提供更多的功能。因?yàn)樗匀皇?Stream的子類,你可以想其 他Stream 一樣使用它(Note: FileStream 包括他自己的緩存能力)。類似地, 你可以使用 System.Security.Cryptography.CryptoStream加密和解密流(Streams),除了它是一個(gè)流應(yīng)用程序不需要知道任何其他的東西。下面展示 了幾種使用不同的Streams調(diào)用打印方法:view sourceprint?1 Memor
20、yStreamms=n ewMemoryStream( newbyte1,2,3,4,5,6,7,8);2 Prin tBytes(ms);3 BufferedStreambuff= newBufferedStream(ms);4 Prin tBytes(buff); ",F5 buff.Close();6 FileStreamfs=n ewFileStream(” ileMode.Ope n);7 Prin tBytes(fs);8 fs.Close();FIMtnwStrtdiHPrintSlreav圖4、使用裝飾模式使用組合動(dòng)態(tài)透明地附加新功能到對(duì)象的能力是裝飾模式的例子,如上
21、圖所示。給定任何Stream的的實(shí)例,你可以通過(guò)包裝在一個(gè) BufferedStream中添加緩沖 訪問(wèn)的能力,而不用改變接口數(shù)據(jù)。因?yàn)槟銉H僅是組合了對(duì)象,這可以在運(yùn)行時(shí) 做,而不像繼承是編譯時(shí)決定的。核心功能通過(guò)一個(gè)接口或者抽象類(如Stream) 定義,所有裝飾都派生自它。這些裝飾自己實(shí)現(xiàn)(或重寫(xiě))接口(或抽象類)中 的方法以提供額外的功能。例如BufferedStream重寫(xiě)Read方法從緩沖中讀取流, 而不是直接從流中讀取。如上面的代碼所示,任何裝飾的組合,不管多復(fù)雜,可 以像只有基類一樣使用。4、適配器模式(AdapterPattern )適配器模式:將一個(gè)類別的接口轉(zhuǎn)接成用戶所期待
22、的。 一個(gè)適配使得因接口不兼 容而不能在一起工作的類工作在一起,做法是將類別自己的接口包裹在一個(gè)已存 在的類中。有兩類適配器模式:對(duì)象適配器模式一一在這種適配器模式中,適配器容納一個(gè)它我包裹的類 的實(shí)例。在這種情況下,適配器調(diào)用被包裹對(duì)象的物理實(shí)體。類適配器模式一一這種適配器模式下, 適配器繼承自已實(shí)現(xiàn)的類(一般多 重繼承)。他們的UML表示分別如下:圖5、對(duì)象適配器模式圖6類適配器模式(來(lái)源:TerryLee的.NET設(shè)計(jì)模式(8):適配器模式(AdapterPattern ).NETFramework的優(yōu)勢(shì)之一就是向后兼容性。從基于.NET的代碼可以輕松的訪問(wèn) 舊的COM寸象,反之亦然。為
23、了在項(xiàng)目中使用 COMA件,必須在VisualStudio 中通過(guò)添加引用對(duì)話框添加引用。在后臺(tái)VisualStudio.NET調(diào)用tlbimp.exe工具創(chuàng)建一個(gè)包含在in terop程序集中的運(yùn)行時(shí)可調(diào)用包裝(Run timeCallableWrapper , RC)類。一旦添加了引用(且 in terop 程序集已 經(jīng)生產(chǎn)了),COMS件就可以像其它托管代碼類一樣使用。如果你在看別人寫(xiě)的 代碼沒(méi)有看到引用列表(且沒(méi)有堅(jiān)持類關(guān)聯(lián)的元數(shù)據(jù)或他們的實(shí)現(xiàn)),你將不知 道哪些類是用.NET的語(yǔ)言寫(xiě)的,哪些是 COMA件。使這種神奇發(fā)生的是RCM COMA件有不同的錯(cuò)誤處理機(jī)制及使用不同的數(shù)據(jù)類型。
24、例如.NETFramework中的字符串使用System.String 類,而COM可能使用BSTR 當(dāng)在.NET代碼中用一個(gè)字符串調(diào)用 COM&件時(shí),你可以像其它托管代碼方法一 樣傳遞一個(gè)System.String 。在RCV內(nèi)部,在COh調(diào)用之前,這個(gè)System.String 轉(zhuǎn)換成COM組件期望的格式,就像BSTR類似地,COM組件的一個(gè)方法調(diào)用典型 地返回HRESUL表示成功或失敗。當(dāng)一個(gè)COM方法調(diào)用返回表示失敗的 HRESULT 時(shí),RCV轉(zhuǎn)化成一個(gè)異常(默認(rèn)情況下),因此它能像其他托管代碼錯(cuò)誤一樣處 理。盡管它們的接口不一樣,但還是允許托管類和COM組件交互,RCW是適
25、配器模式的例子。適配器模式使一個(gè)接口適合另一個(gè),COM并不理解System.String類, 因此RCW1配器使其適應(yīng)為可以理解的。即使你不能改變舊的組件工作機(jī)制,你 仍可以與它交互。這種情況經(jīng)常使用適配器。適配器類本身包含了一個(gè)適配(Adaptee),將來(lái)自客戶端的調(diào)用轉(zhuǎn)化為合適的 和順序的調(diào)用。雖然聽(tīng)起來(lái)像裝飾模式,它們之間有幾個(gè)關(guān)鍵的不同。裝飾模式中,組合的對(duì)象接口是相同的;適配器模式中,你可以改變整個(gè) 接口。適配器模式中,給他們定義了一個(gè)明確的序列,適配必須包含在適配器中; 裝飾模式中,裝飾類不必知道它包裝了 1個(gè)或500個(gè)其它類,因?yàn)榻涌谑?相同的。因此使用裝飾模式對(duì)應(yīng)用程序時(shí)透明的
26、,然而使用適配器模式不是。5、工廠模式(FactoryPattern )工廠模式:通過(guò)調(diào)用不同的方法返回需要的類, 而不是去實(shí)例化具體的類。對(duì)實(shí) 例創(chuàng)建進(jìn)行了包裝。工廠方法是一組方法,他們針對(duì)不同條件返回不同的類實(shí)例, 這些類一般有共同的父類。它的 UML表示如下:圖7、工廠模式的UML表示(來(lái)源:TerryLee的.NET設(shè)計(jì)模式(5):工廠方法模式(Factory Method )許多情況下,在框架(Framework)中你可以自己不調(diào)用一個(gè) struct或class 的構(gòu)造器而獲取一個(gè)新的實(shí)例。System.C on vert類包含了一系列的靜態(tài)方法向 這樣工作。例如,將一個(gè)整數(shù)轉(zhuǎn)換為布
27、爾類型,你可以調(diào)用Con vert.ToBollean并傳遞一個(gè)整數(shù)。如果整數(shù)是一個(gè)非零值則這個(gè)方法的返回值是一個(gè)新的Boolean并設(shè)為“ true ”,否則是“ false ”。Con vert類為我們創(chuàng)建Boolean 實(shí)例,并設(shè)為正確的值,其它的類型轉(zhuǎn)換也是類似。Int32和Double上的Parse 方法返回這些對(duì)象的新實(shí)例并根據(jù)給定的字符串設(shè)置合適的值。這種創(chuàng)建新對(duì)象實(shí)例的策略稱為工廠模式。不用調(diào)用對(duì)象的構(gòu)造器,你可以要 求對(duì)象工廠為你創(chuàng)建一個(gè)實(shí)例。如此一來(lái)可以隱藏創(chuàng)建對(duì)象的復(fù)雜性(就像如何 從一個(gè)字符串解析為一個(gè)Double值,Double.Parse )。如果你想改變創(chuàng)建對(duì)象
28、的細(xì)節(jié),你僅需要改變工廠它本身,你不必修改每個(gè)調(diào)用構(gòu)造器的地方。這些類型轉(zhuǎn)換方法是工廠模式的變種,因?yàn)樵趩?wèn)題中你不必使用這個(gè)工廠創(chuàng)建對(duì) 象。一個(gè)更純的工廠模式的例子是 類,用來(lái)發(fā)出請(qǐng)求(request )和從In ternet 上的資源接受響應(yīng)(respo nse )。FTP HTTP和文件 系統(tǒng)請(qǐng)求默認(rèn)頁(yè)支持。為了創(chuàng)建一個(gè)請(qǐng)求,調(diào)用Create方法和傳遞一個(gè)URI。Create方法決定合適的請(qǐng)求協(xié)議,且返回合適的WebReques的子類:HttpWebRequest、FtpWebReques( .NETFramework2.0新增的)、FileWebRequest。 調(diào)用者不需要知道每個(gè)特定
29、的協(xié)議,僅需知道如何調(diào)用工廠和使用WebRequest獲取返回值。如果URI從一個(gè)HTTP地址改變?yōu)镕TP地址,代碼根本不用改變。 這是工廠模式的另一種常用用法。 父類作為一個(gè)工廠,且根據(jù)客戶端傳遞的參數(shù) 返回特定派生類。就像 WebRequest例子,它隱藏了選擇合適派生類的復(fù)雜性。6 策略模式(StrategyPattern ) 策略模式:指對(duì)象有某個(gè)行為,但是在不同的場(chǎng)景中,該行為有不同的實(shí)現(xiàn)算法。 比如每個(gè)人都要“交個(gè)人所得稅”,但是“在美國(guó)交個(gè)人所得稅”和“在中國(guó)交 個(gè)人所得稅”就有不同的算稅方法。它的 UML表示如下:策略模式的UML表示(來(lái)源:維基百科)數(shù)組(Array )和數(shù)組
30、列表(ArrayList )都提供通過(guò)Sort方法對(duì)集合中的對(duì)象 排序的功能。實(shí)際上,ArrayList.Sort 僅對(duì)隱含的數(shù)組調(diào)用Sort。這些方法使 用的是快速排序(QuickSor)算法。默認(rèn),Sort方法使用IComparable實(shí)現(xiàn)每 個(gè)元素之間的比較。有時(shí),使用不同的方法對(duì)同一列表排序非常有用。例如,字符串?dāng)?shù)組的排序可能是對(duì)大小寫(xiě)敏感的或不區(qū)分大小寫(xiě)的。要做到這點(diǎn),Sort函數(shù)存在重載并以一個(gè)IComparer作為參數(shù);然后IComparer.Compare用于進(jìn)行 比較。重載允許類的用戶任何內(nèi)置的ICompares或自定義的,而不用做修改甚至 不用知道Array、ArrayLi
31、st、或Quicksort算法的實(shí)現(xiàn)細(xì)節(jié)。將比較算法的選擇留給類的用戶,像這種情況就是策略模式。使用策略模式允許 有許多不同的可替換的算法。Quicksort本身只需要一個(gè)方法來(lái)相互比較對(duì)象。 通過(guò)提供一個(gè)接口調(diào)用比較,由調(diào)用方自由選擇可替換的適合特定需要的比較算 法。Quicksort的代碼可以保持不改變。J AJcMitha Viriawt 1 F1 . T" 1 I 1 T . E j iF '51 Algorithm Vidant 2圖9、策略行為.NETFramework2.0的一個(gè)新的泛型集合類型 List<T>,還利用大量使用的策 略模式,如上圖所示
32、。除了更新了排序方法,find-related方法,BinarySearch,其它以根據(jù)調(diào)用者需求改變算法的參數(shù)。在FindAII<T>方法中使用一個(gè)Predicate<T>委托使調(diào)用者使用任何方法作為 List<T>的過(guò)濾器,只要它接受的 對(duì)象類型并返回一個(gè)布爾值。組合匿名方法,客戶可以容易地基于屬性和列表中 對(duì)象的方法過(guò)濾列表,而不用引入依賴于List<T>類本身。使用策略模式使復(fù)雜的處理過(guò)程,諸如排序,容易地修改以適合特定的目的,這意味著你可以編寫(xiě)和維護(hù)較少的代碼。7、ASP.NET中的組合模式(CompositePattern )組合模式
33、:將對(duì)象組合成樹(shù)形結(jié)構(gòu)以表示“部分整體”的層次結(jié)構(gòu)。組合模式使得用戶對(duì)單個(gè)對(duì)象和使用具有一致性。它的 UML表示為:CI ientforaach child in child nanchild .QpeiBLjOMf)I圖10、組合模式的UML表示(來(lái)源:TerryLee的.NET設(shè)計(jì)模式(11):組合模式(Composite Pattern )ASP.NET的request/response 管道(pipeline )是一個(gè)復(fù)雜的系統(tǒng)。模式用于設(shè)計(jì)管道本身和控件體系結(jié)構(gòu)有效地平衡它的可擴(kuò)展性能和簡(jiǎn)化編程。在深入挖掘管道之前,我們檢查編程模型本身使用的模式。當(dāng)處理對(duì)象集合時(shí),通常適合單個(gè)對(duì)象和
34、整個(gè)集合。 考慮一個(gè)ASP.NET控件,- 個(gè)控件可能是一個(gè)簡(jiǎn)單的單個(gè)元素如 Literal ,或可能是一個(gè)有子控件的復(fù)雜的 集合如DataGrid。不管怎樣,任一這些控件上調(diào)用 Render方法都將執(zhí)行相同的 顯示功能。當(dāng)集合的每個(gè)元素可能自己包含其它對(duì)象的集合時(shí),使用組合模式是合適的。組合模式是一個(gè)簡(jiǎn)單的方法來(lái)表示樹(shù)形集合,而不用對(duì)父節(jié)點(diǎn)和葉子節(jié)點(diǎn)區(qū)別對(duì)象。組合模式的權(quán)威例子是依賴于一個(gè)抽象基類,Compo nent包含添加和刪除孩子、 孩子和父親之間的通用操作方法。 ASP.NET正是對(duì)使用 這種模式。Control表示Component基類,它有一些操作,諸如處理子控件(如 子空間屬性
35、)、標(biāo)準(zhǔn)操作、屬性如Render和Visible (譯注:定義由所有ASP.NET 服務(wù)器控件共享的屬性、方法和事件)。每個(gè)對(duì)象,不管是原始的對(duì)象(如Literal ) 或組合對(duì)象(如DataGrid ),讀繼承自這個(gè)基類。因?yàn)榭丶嵌鄻拥?,有一些中間繼承類如 WebControl和BaseDataList,是其它 控件的基類。雖然這些類公開(kāi)一些額外的屬性和方法,但他們?nèi)匀槐A艉⒆拥墓?理功能和從Control繼承的核心操作。事實(shí)上,使用組合模式有助于隱藏他們的 復(fù)雜性,如果需要的話。 不管是一個(gè)Literal控件還是一個(gè)DataGrid控件,使 用組合模式意味著你僅需要調(diào)用 Ren der,
36、事情會(huì)自行解決。8、模板方法模式(TemplateMethodPattern ) 模板方法模式:定義了一個(gè)算法的步驟,并允許次類別為一個(gè)或多個(gè)步驟提供其 實(shí)踐方式。讓次類別在不改變算法架構(gòu)的情況下,重新定義算法中的某些步驟。 模板方法多用在:某些類別的算法中,實(shí)做了相同的方法,造成程序碼的重復(fù) 控制次類別必須遵守的一些事項(xiàng)。它的UML表示如下:U .、G AhsiraciClasaoonneTningOjif,”,F(xiàn)r imi i wQpealion 耳 it.FFinitjOyEntianlPrimli«Optrailoril()jPrinidi 足 Opentthn?屯irdoA
37、ht-Q d TanplalE LlEtho d QIt .一 d»SoiTiEiiiingQ建 CcncreteClass,I Frunib總OpradoniqFmirtiJEO-pritiKinZQ圖11、模板方法的UML表示(來(lái)源:一 d»Soin»thhiig(|維基百科)當(dāng)ASP.NET控件的標(biāo)準(zhǔn)庫(kù)滿足不了你的需求,你有幾種選擇如何創(chuàng)建自己的。對(duì) 簡(jiǎn)單的控件僅用在一個(gè)項(xiàng)目中,用戶控件是最好的選擇。當(dāng)控件用在集合 Web 應(yīng)用程序中或要求更多的功能,一個(gè)自定義服務(wù)器控件也許是最好的選擇。當(dāng)處理自定義控件,有兩個(gè)一般的類型:控件組合已存在的控件的功能(稱為組
38、 合模式)、控件有一個(gè)唯一的視覺(jué)表示。處理創(chuàng)建這些類型的控件的過(guò)程類似。對(duì)應(yīng)組合控件,創(chuàng)建一個(gè)新的類繼承自一個(gè)控件基類(像Control或WebControl), 然后重寫(xiě)CreateChildControls 方法(譯注:該方法由 ASP.NET頁(yè)面框架調(diào)用, 以通知使用基于合成的實(shí)現(xiàn)的服務(wù)器控件創(chuàng)建它們包含的任何子控件,以便為回發(fā)或呈現(xiàn)做準(zhǔn)備)。對(duì)于其它自定義控件,你需要重寫(xiě)的 Ren der且使用 HtmITextWriter參數(shù)用于為你的控件直接輸出 HTML不管你選擇的自定義控件的樣式,你不必寫(xiě)任何處理所有控件通用的功能,如在適當(dāng)?shù)臅r(shí)間加載和保存 ViewState,允許PostBa
39、ck事件去處理,且確??丶?生命周期事件以正確的順序發(fā)生??丶趺礃蛹虞d、呈現(xiàn)、卸載的主要算法包含 在控件基類中。你的控件的特定細(xì)節(jié)在控件算法的特定地方實(shí)現(xiàn)(CreateChildCo ntrols 或 Ren der方法)。這是模板方法模式的一個(gè)例子。主要算法框架定義在一個(gè)基類中,且子類可以插入他們自己的細(xì)節(jié)而不影響算法本身,如圖12所示。一個(gè)組合控件和一個(gè)自定義控件都共享同樣的一般生命周期,但是他們以完全不同的視ClMtAVtdtrt: CImU DtStmrlhinW 1SR. 1DvtrrMt St*i 1覺(jué)表示。圖12、模板方法模式這個(gè)模式類似于策略模式,他們?cè)诜秶头椒ㄉ喜煌?。?/p>
40、略模式用于允許調(diào)用者改變整個(gè)算法,例如如何比較兩個(gè)對(duì)象,然而 模板方法模式用于改變算法的步驟。正是因?yàn)檫@點(diǎn),策略模式是更粗粒度 的,他們的不同客戶端實(shí)現(xiàn)可以有巨大的不同,然而模板方法模式保持框架相同。另一個(gè)主要不同點(diǎn)是,策略模式使用委托,然而模板方法模式使用繼承。 上面排序例子的策略模式,比較算法委托于IComparer參數(shù);但是自定義 控件中,你子類的基類和重寫(xiě)方法去做改變。然而,他們都使你容易地修改處理過(guò)程以適合你的特定需求。9、ASP.NET管道中的模式(PatternsintheASP.NETPipeline )當(dāng)客戶端請(qǐng)求一個(gè)ASPX網(wǎng)頁(yè),在最終以HTML顯示到客戶端的瀏覽器之前,請(qǐng)
41、求 穿過(guò)許多步驟。首先,請(qǐng)求被IIS處理和路由到合適的ISAPI擴(kuò)展。ASP.NET的 ISAPI 擴(kuò)展(aspnet_isapi.dll )路由請(qǐng)求到 ASP.NETT作進(jìn)程。13、ASP.NET青求管道在這一點(diǎn),請(qǐng)求開(kāi)始與處理請(qǐng)求的類進(jìn)行交互。請(qǐng)求被傳遞到一個(gè)HttpApplication 。一般地,這個(gè)類在 Global.asax的后置代碼文件中創(chuàng)建。 HttpApplicati on然后傳遞請(qǐng)求給一些 HTTP模塊。這些類實(shí)現(xiàn)了 IHttpModule接口且在傳遞給下一模塊之前可以修改請(qǐng)求(甚至可以停止請(qǐng)求)。ASP.NET提供了一些標(biāo)準(zhǔn)的模塊提供常用的功能,包括FormsAuthe
42、nticatio nM odule、PassportAuthe nticati onM odule、Win dowsAuthe nticatio n 、Sessi on StateModule等等。最終,請(qǐng)求結(jié)束在一個(gè)IHttpHandler,最常用的是 的 IHttpHandler.ProcessRequest 方法。Page產(chǎn)生合適的事件(例如 Init、Load、 Render),處理ViewState,提供ASP.NET勺編程模型。圖13展示了一個(gè)整理 輪廓。在這個(gè)處理過(guò)程中采用了幾個(gè)模式,更深入的可以參考Marti nF owler's PatternsofE nterpri
43、seApplicatio nArchitecture(Addis on-Wes ley,2002)。下面介紹其中用到的幾個(gè)模式。9.1、截取過(guò)濾器模式(InterceptingFilterPattern)一旦一個(gè)請(qǐng)求到達(dá) HttpApplication ,它將傳遞到一些IHttpModules 。每個(gè)模塊 是獨(dú)立的且僅有數(shù)量有限的控制加在調(diào)用順序上。HttpApplication 類公開(kāi)一系 列的事件,在請(qǐng)求的處理過(guò)程中產(chǎn)生這些事件包括 Beg in Request、AuthenticateRequest 、 AuthorizeRequest 、 EndRequest。當(dāng) HttpApplic
44、ation 加載一個(gè)模塊,它調(diào)用IHttpModule接口的Init方法,允許模塊注冊(cè)關(guān)心它的 一些事件。作為一個(gè)給定的請(qǐng)求被處理,事件以合適的順序產(chǎn)生且所有注冊(cè)的模 塊可以與請(qǐng)求交互。因此,模塊可以控制在它被調(diào)用的階段,但不是這一階段的確切順序。這些模塊是截取過(guò)濾模式的例子, 這個(gè)模式表示一個(gè)過(guò)濾器鏈,每個(gè)過(guò)濾器依次 有機(jī)會(huì)修改請(qǐng)求(或消息)傳遞他們。圖 14展示了這個(gè)過(guò)程的一個(gè)簡(jiǎn)單的流程 圖。這個(gè)模式的關(guān)鍵思想是過(guò)濾器是獨(dú)立的, 過(guò)濾器可以修改傳遞到它的請(qǐng)求。圖14、請(qǐng)求流程有幾種不同的截取過(guò)濾器模式變種的實(shí)現(xiàn),一種是 ASP.NET勺基于事件的模型。 一個(gè)簡(jiǎn)單的變種包括維護(hù)一個(gè)過(guò)濾器列表
45、并對(duì)它迭代,依次對(duì)它們每個(gè)調(diào)用一個(gè) 方法。這是 WebServiceEnhancements (WSE 為 ASP.ENTService如何使用這個(gè) 模式。每個(gè)過(guò)濾器擴(kuò)展自SoaplnputFilter (為請(qǐng)求消息)或SoapOutputFilter(為響應(yīng)),重寫(xiě)ProcessMessage方法執(zhí)行過(guò)濾器的工作。另外一種選擇是通過(guò)裝飾模式實(shí)現(xiàn)截取過(guò)濾器。每個(gè)過(guò)濾器將包裝它的后繼,執(zhí)行預(yù)處理,調(diào)用它的后繼,然后執(zhí)行后處理。通過(guò)遞歸組合構(gòu)建鏈,從后往前。 這個(gè)模式用于實(shí)現(xiàn).NETRemoting管道接收器。無(wú)論其實(shí)現(xiàn),結(jié)果是獨(dú)立過(guò)濾器的動(dòng)態(tài)可配置鏈。因?yàn)樗麄兪仟?dú)立的,這些過(guò)濾 器可以容易地在其他應(yīng)用程序中重排序和重用。通用任務(wù)如身份鑒定或日志可以封裝在一個(gè)過(guò)濾器中且反復(fù)使用。這些任務(wù)可以在請(qǐng)求到達(dá)HttpHandler之前被 過(guò)濾器鏈處理,保持處理代碼整潔。9.2、頁(yè)面控制器模式(PageControllerPattern)實(shí)現(xiàn)ASP.NET編程模型的核心部分。每當(dāng)你要添加一個(gè)邏 輯頁(yè)面到一個(gè) Web應(yīng)用程序,你可以創(chuàng)建一個(gè) WebFor(通過(guò)一個(gè)ASPX文件和 它的后置代碼文件表示)。然后你可以編寫(xiě)代碼處理新頁(yè)面的具體需求,無(wú)論是 通過(guò)處理頁(yè)面級(jí)事件,顯示一個(gè)組控件,或加載和操作數(shù)據(jù)。應(yīng)用程序中的每個(gè) 邏輯頁(yè)面有一個(gè)相應(yīng)的WebForm
溫馨提示
- 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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 嬰兒用品跨境貿(mào)易的機(jī)遇與挑戰(zhàn)
- 英語(yǔ)閱讀競(jìng)賽試卷
- 車輛交易稅費(fèi)抵扣貸款本金協(xié)議范本
- 成都房產(chǎn)交易合同范本:房屋交易售后服務(wù)及保障措施
- 隧道支護(hù)處理方案
- 車間燈光節(jié)能方案模板
- 食品項(xiàng)目資金使用方案
- 塔吊操作人員勞務(wù)派遣與權(quán)益保障合同
- 公共停車場(chǎng)車位租用及停車秩序管理合同
- 藏式風(fēng)格民宿客房裝修設(shè)計(jì)監(jiān)理合同
- 2025至2030年中國(guó)電子束曝光系統(tǒng)行業(yè)市場(chǎng)研究分析及發(fā)展前景研判報(bào)告
- 2025屆重慶市梁平區(qū)英語(yǔ)七年級(jí)第二學(xué)期期末調(diào)研模擬試題含答案
- 2025年安徽省高考物理試卷真題(含答案解析)
- 校園文印室外包服務(wù)投標(biāo)方案(技術(shù)標(biāo))
- 飛行影院項(xiàng)目商業(yè)計(jì)劃書(shū)
- 創(chuàng)業(yè)公司文件管理制度
- 2022年江蘇省徐州市中考道德與法治試題(解析版)
- 高速公路房建工程施工項(xiàng)目施工組織設(shè)計(jì)1
- 情緒價(jià)值話術(shù)課件
- 成本削減方案
- 2025山東兗礦集團(tuán)招聘60人易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
評(píng)論
0/150
提交評(píng)論