C#設計模式(李建忠)--精選文檔_第1頁
C#設計模式(李建忠)--精選文檔_第2頁
已閱讀5頁,還剩212頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、單件模式(Singleton Pattern)動機(Motivation): 在軟件系統中,經常有這樣一些特殊的類,必須保證它們在系統中只存在一個實例,才能確保它們的邏輯正確性、以及良好的效率。 如何繞過常規的構造器,提供一種機制來保證一個類只創建一個實例? 這應該是類設計者的責任,而不是類使用者的責任。結構圖: 意圖: 保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。 -GOF生活的例子: 適用性: (1)當類只能有一個實例而且客戶可以從一個眾所周知的訪問點訪問它時。 (2)當這個唯一實例應該是通過子類化可擴展的,并且客戶應該無需更改代碼就能使用一個擴展的實例時。代碼實現:(1)單線程

2、Singleton實現 classSingleThread_SingletonprivatestaticSingleThread_Singletoninstance=null;privateSingleThread_Singleton()publicstaticSingleThread_SingletonInstancegetif(instance=null)instance=newSingleThread_Singleton();returninstance;以上代碼在單線程情況下不會出現任何問題。但是在多線程的情況下卻不是安全的。如兩個線程同時運行到 if(instance=null)判斷

3、是否被實例化,一個線程判斷為True后,在進行創建instance=newSingleThread_Singleton();之前,另一個線程也判斷(instance=null),結果也為True.這樣就就違背了Singleton模式的原則(保證一個類僅有一個實例)。怎樣在多線程情況下實現Singleton?(2)多線程Singleton實現:1classMultiThread_Singleton23privatestaticvolatileMultiThread_Singletoninstance=null;4privatestaticobjectlockHelper=newobject();

4、5privateMultiThread_Singleton()6publicstaticMultiThread_SingletonInstance78get910if(instance=null)1112lock(lockHelper)1314if(instance=null)1516instance=newMultiThread_Singleton();17181920returninstance;212223 此程序對多線程是安全的,使用了一個輔助對象lockHelper,保證只有一個線程創建實例(如果instance為空,保證只有一個線程instance=newMultiThread_S

5、ingleton();創建唯一的一個實例)。(Double Check)請注意一個關鍵字volatile,如果去掉這個關鍵字,還是有可能發生線程不是安全的。volatile 保證嚴格意義的多線程編譯器在代碼編譯時對指令不進行微調。(3)靜態Singleton實現3classStatic_Singleton45 public staticreadonlyStatic_Singletoninstance=newStatic_Singleton();6privateStatic_Singleton()7以上代碼展開等同于1classStatic_Singleton23 public staticre

6、adonlyStatic_Singletoninstance;4staticStatic_Singleton()56instance=newStatic_Singleton();78privateStatic_Singleton()9由此可以看出,完全符合Singleton的原則。優點: 簡潔,易懂缺點: 不可以實現帶參數實例的創建抽象工廠模式(Abstract Factory)常規的對象創建方法:/創建一個Road對象Roadroad=newRoad();new 的問題: 實現依賴,不能應對“具體實例化類型”的變化。解決思路: 封裝變化點-哪里變化,封裝哪里 潛臺詞: 如果沒有變化,當然不需

7、要額外的封裝!工廠模式的緣起 變化點在“對象創建”,因此就封裝“對象創建” 面向接口編程-依賴接口,而非依賴實現最簡單的解決方法:1classRoadFactory2publicstaticRoadCreateRoad()34returnnewRoad();567/創建一個Road對象8Roadroad=roadFactory.CreateRoad();創建一系列相互依賴對象的創建工作:假設一個游戲開場景:我們需要構造道路、房屋、地道,從林.等等對象工廠方法如下:1classRoadFactory23publicstaticRoadCreateRoad()45returnnewRoad();6

8、7publicstaticBuildingCreateBuilding()89returnnewBuilding();1011publicstaticTunnelCreateTunnel()1213returnnewTunnel();1415publicstaticJungleCreateJungle()1617returnnewJungle();1819調用方式如下: 1Roadroad= RoadFactory.CreateRoad();3Buildingbuilding=RoadFactory.CreateBuilding();4Tunneltunnel=RoadFactory.Crea

9、teTunnel();5Junglejungle=RoadFactory.CreateJungle();如上可見簡單工廠的問題: 不能應對不同系列對象的變化。比如有不同風格的場景-對應不同風格的道路,房屋、地道.如何解決: 使用面向對象的技術來封裝變化點。動機(Motivate): 在軟件系統中,經常面臨著一系統相互依賴的對象的創建工作:同時,由于需求的變化,往往存在更多系列對象的創建工作。 如何應對這種變化?如何繞過常規的對象創建方法(new),提供一種封裝機制來避免客戶程序和這種多系列具體對象創建工作的緊耦合?意圖(Intent): 提供一個創建一系列相關或相互依賴對象的接口,而無需指定它

10、們具體的類。 -設計模式GOF結構圖(Struct): 適用性: 1.一個系統要獨立于它的產品的創建、組合和表示時。 2.一個系統要由多個產品系統中的一個來配置時。 3.當你要強調一系列相關的產品對象的設計以便進行聯合使用時。 4.當你提供一個產品類庫,而只想顯示它們的接口不是實現時。生活例子: 結構圖代碼實現:1abstractclassAbstractFactory23publicabstractAbstractProductACreateProductA();4publicabstractAbstractProductBCreateProductB();51abstractclassAb

11、stractProductA23publicabstractvoidInteract(AbstractProductBb);41abstractclassAbstractProductB23publicabstractvoidInteract(AbstractProductAa);41classClient23privateAbstractProductAAbstractProductA;4privateAbstractProductBAbstractProductB;5publicClient(AbstractFactoryfactory)67AbstractProductA=factory

12、.CreateProductA();8AbstractProductB=factory.CreateProductB();910publicvoidRun()1112AbstractProductB.Interact(AbstractProductA);13AbstractProductA.Interact(AbstractProductB);14151classConcreteFactory1:AbstractFactory23publicoverrideAbstractProductACreateProductA()45returnnewProductA1();67publicoverri

13、deAbstractProductBCreateProductB()89returnnewProductB1();10111classConcreteFactory2:AbstractFactory23publicoverrideAbstractProductACreateProductA()45returnnewProdcutA2();67publicoverrideAbstractProductBCreateProductB()89returnnewProductB2();10111classProductA1:AbstractProductA23publicoverridevoidInt

14、eract(AbstractProductBb)45Console.WriteLine(this.GetType().Name+interactwith+b.GetType().Name);671classProductB1:AbstractProductB23publicoverridevoidInteract(AbstractProductAa)45Console.WriteLine(this.GetType().Name+interactwith+a.GetType().Name);671classProdcutA2:AbstractProductA23publicoverridevoi

15、dInteract(AbstractProductBb)45Console.WriteLine(this.GetType().Name+interactwith+b.GetType().Name);671classProductB2:AbstractProductB23publicoverridevoidInteract(AbstractProductAa)45Console.WriteLine(this.GetType().Name+interactwith+a.GetType().Name);671publicstaticvoidMain()23/Abstractfactory14Abst

16、ractFactoryfactory1=newConcreteFactory1();5Clientc1=newClient(factory1);6c1.Run();7/Abstractfactory28AbstractFactoryfactory2=newConcreteFactory2();9Clientc2=newClient(factory2);10c2.Run();11Abstract Factory注意的幾點: 如果不存在”多系列對象創建“的需求變化,則沒必要應用Abstract Factory模式,靜態工廠方法足矣。 系列對象指的是這些對象之間有相互依賴、或作用的關系。例如游戲開發

17、場景中的道路與房屋依賴,“道路”與“地道”的依賴。Abstract Factory模式主要在于應對新系列的需求變動。其缺點在于難以應對”新對象“的需求變動。Abstract Factory模式經常和Factory Method模式共同組合來應對“對象創建”的需求變化建造者模式(Builder)Builder模式的緣起: 假設創建游戲中的一個房屋House設施,該房屋的構建由幾部分組成,且各個部分富于變化。如果使用最直觀的設計方法,每一個房屋部分的變化,都將導致房屋構建的重新修正.動機(Motivation): 在軟件系統中,有時候面臨一個復雜對象的創建工作,其通常由各個部分的子對象用一定算法構

18、成;由于需求的變化,這個復雜對象的各個部分經常面臨著劇烈的變化,但是將它們組合到一起的算法卻相對穩定。 如何應對種變化呢?如何提供一種封裝機制來隔離出復雜對象的各個部分的變化,從而保持系統中的穩定構建算法不隨需求的改變而改變?意圖(Intent): 將一個復雜對象的構建與其表示相分離,使得同樣的構建過程可以創建不同的表示。 -設計模式GOF結構圖(Struct): 協作(Collaborations): 生活中的例子: 適用性: 1.當創建復雜對象的算法應該獨立于該對象的組成部分以及它們的裝配方式時。 2.當構造過程必須允許被構造的對象有不同的表示時。實例代碼:Builder類:1public

19、abstractclassBuilder23publicabstractvoidBuildDoor();4publicabstractvoidBuildWall();5publicabstractvoidBuildWindows();6publicabstractvoidBuildFloor();7publicabstractvoidBuildHouseCeiling();89publicabstractHouseGetHouse();10Director類:這一部分是 組合到一起的算法(相對穩定)。 1publicclassDirector23publicvoidConstruct(Buil

20、derbuilder)45builder.BuildWall();6builder.BuildHouseCeiling();7builder.BuildDoor();8builder.BuildWindows();9builder.BuildFloor();1011ChineseBuilder類1publicclassChineseBuilder:Builder23privateHouseChineseHouse=newHouse();4publicoverridevoidBuildDoor()56Console.WriteLine(thisDoorsstyleofChinese);78pub

21、licoverridevoidBuildWall()910Console.WriteLine(thisWallsstyleofChinese);1112publicoverridevoidBuildWindows()1314Console.WriteLine(thisWindowssstyleofChinese);1516publicoverridevoidBuildFloor()1718Console.WriteLine(thisFloorsstyleofChinese);1920publicoverridevoidBuildHouseCeiling()2122Console.WriteLi

22、ne(thisCeilingsstyleofChinese);2324publicoverrideHouseGetHouse()2526returnChineseHouse;2728RomanBuilder類:1classRomanBuilder:Builder23privateHouseRomanHouse=newHouse();4publicoverridevoidBuildDoor()56Console.WriteLine(thisDoorsstyleofRoman);78publicoverridevoidBuildWall()910Console.WriteLine(thisWall

23、sstyleofRoman);1112publicoverridevoidBuildWindows()1314Console.WriteLine(thisWindowssstyleofRoman);1516publicoverridevoidBuildFloor()1718Console.WriteLine(thisFloorsstyleofRoman);1920publicoverridevoidBuildHouseCeiling()2122Console.WriteLine(thisCeilingsstyleofRoman);2324publicoverrideHouseGetHouse(

24、)2526returnRomanHouse;2728ChineseBuilder和RomanBuilder這兩個是:這個復雜對象的兩個部分經常面臨著劇烈的變化。1publicclassClient23publicstaticvoidMain(stringargs)45Directordirector=newDirector();67Builderinstance;89Console.WriteLine(PleaseEnterHouseNo:);1011stringNo=Console.ReadLine();1213stringhouseType=ConfigurationSettings.Ap

25、pSettingsNo+No;1415instance=(Builder)Assembly.Load(House).CreateInstance(House.+houseType);1617director.Construct(instance);1819Househouse=instance.GetHouse();20house.Show();2122Console.ReadLine();23241234567Builder模式的幾個要點:Builder模式 主要用于“分步驟構建一個復雜的對象”。在這其中“分步驟”是一個穩定的乘法,而復雜對象的各個部分則經常變化。Builder模式主要在于應

26、對“復雜對象各個部分”的頻繁需求變動。其缺點在于難以應對“分步驟構建算法”的需求變動。Abstract Factory模式解決“系列對象”的需求變化,Builder模式解決“對象部分”的需求變化。Builder械通常和Composite模式組合使用工廠方法模式(Factory Method)耦合關系: 動機(Motivation): 在軟件系統中,由于需求的變化,這個對象的具體實現經常面臨著劇烈的變化,但它卻有比較穩定的接口。 如何應對這種變化呢?提供一種封裝機制來隔離出這個易變對象的變化,從而保持系統中其它依賴的對象不隨需求的變化而變化。意圖(Intent): 定義一個用戶創建對象的接口,讓

27、子類決定實例哪一個類。Factory Method使一個類的實例化延遲到子類。 -設計模式GOF結構圖(Struct): 生活實例: 適用性: 1.當一個類不知道它所必須創建的對象類的時候。 2.當一個類希望由它子類來指定它所創建對象的時候。 3.當類將創建對象的職責委托給多個幫助子類中的某個,并且你希望將哪一個幫助子類是代理者這一信息局部化的時候。實例代碼:CarFactory類:1publicabstractclassCarFactory23publicabstractCarCarCreate();4Car類: 1publicabstractclassCar23publicabstract

28、voidStartUp();4publicabstractvoidRun();5publicabstractvoidStop();67HongQiCarFactory類:1publicclassHongQiCarFactory:CarFactory23publicoverrideCarCarCreate()45returnnewHongQiCar();67BMWCarFactory類:1publicclassBMWCarFactory:CarFactory23publicoverrideCarCarCreate()45returnnewBMWCar();67HongQiCar類:1public

29、classHongQiCar:Car23publicoverridevoidStartUp()45Console.WriteLine(TestHongQiCarstart-upspeed!);67publicoverridevoidRun()89Console.WriteLine(TheHongQiCarrunisveryquickly!);1011publicoverridevoidStop()1213Console.WriteLine(Theslowstoptimeis3second);1415BMWCar類:1publicclassBMWCar:Car23publicoverridevo

30、idStartUp()45Console.WriteLine(TheBMWCarstart-upspeedisveryquickly);67publicoverridevoidRun()89Console.WriteLine(TheBMWCarrunisquitelyfastandsafe!);1011publicoverridevoidStop()1213Console.WriteLine(Theslowstoptimeis2second);1415app.config1234567Program類:1classProgram23staticvoidMain(stringargs)45Con

31、sole.WriteLine(PleaseEnterFactoryMethodNo:);6Console.WriteLine(*);7Console.WriteLine(noFactoryMethod);8Console.WriteLine(1HongQiCarFactory);9Console.WriteLine(2BMWCarFactory);10Console.WriteLine(*);11intno=Int32.Parse(Console.ReadLine().ToString();12stringfactoryType=ConfigurationManager.AppSettings

32、No+no;13/CarFactoryfactory=newHongQiCarFactory();14CarFactoryfactory=(CarFactory)Assembly.Load(FactoryMehtod).CreateInstance(FactoryMehtod.+factoryType);15Carcar=factory.CarCreate();16car.StartUp();17car.Run();18car.Stop();192021Factory Method 模式的幾個要點:Factory Method模式主要用于隔離類對象的使用者和具體類型之間的耦合關系。面對一個經常

33、變化的具體類型,緊耦合關系會導致軟件的脆弱。Factory Method模式通過面向對象的手法,將所要創建的具體對象工作延遲到子類,從而實現一種擴展(而非更改)的策略,較好地解決了這種緊耦合關系。Factory Mehtod模式解決單個對象的需求變化,AbstractFactory模式解決系列對象的需求變化,Builder模式解決對象部分的需求變化原型模式(Prototype)依賴關系倒置: 動機(Motivate): 在軟件系統中,經常面臨著“某些結構復雜的對象”的創建工作;由于需求的變化,這些對象經常面臨著劇烈的變化,但是它們卻擁有比較穩定一致的接口。 如何應對這種變化?如何向“客戶程序(

34、使用這些對象的程序)隔離出“這些易變對象”,從而使得“依賴這些易變對象的客戶程序”不隨著需求改變而改變?意圖(Intent): 用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象。 -設計模式GOF結構圖(Struct): 生活例子: 適用性: 1當一個系統應該獨立于它的產品創建,構成和表示時; 2當要實例化的類是在運行時刻指定時,例如,通過動態裝載; 3為了避免創建一個與產品類層次平行的工廠類層次時; 4當一個類的實例只能有幾個不同狀態組合中的一種時。建立相應數目的原型并克隆它們可能比每次用合適的狀態手工實例化該類更方便一些。 示意性代碼例子:1publicabstractcla

35、ssNormalActor23publicabstractNormalActorclone();41publicclassNormalActorA:NormalActor23publicoverrideNormalActorclone()45Console.WriteLine(NormalActorAiscall);6return(NormalActor)this.MemberwiseClone();7891publicclassNormalActorB:NormalActor23publicoverrideNormalActorclone()45Console.WriteLine(Norma

36、lActorBwascalled);6return(NormalActor)this.MemberwiseClone();789 public class GameSystem public void Run(NormalActor normalActor) NormalActor normalActor1 = normalActor.clone(); NormalActor normalActor2 = normalActor.clone(); NormalActor normalActor3 = normalActor.clone(); NormalActor normalActor4 = normalActor.clone(); NormalActor normalActor5 = normalActor.clone(); class Program static void Main(string args) GameSystem gameSystem = new GameSystem(); gameSystem.Run(new NormalActorA(); 如果又需要創建新的對象(flyActor),只需創建此抽象類,然后具體類進行克隆。 public abstract class FlyActor public abstract FlyActor

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論