《游戏设计--经典文档-C#23种设计模式.docx》由会员分享,可在线阅读,更多相关《游戏设计--经典文档-C#23种设计模式.docx(269页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、c# 23种设计模式China Document 4 Colors1.1 节工期How are you1.1.1 完成日期12节创建型模式12.1 单件模式(Singleton Pattern)动机(Motivation):在软件系统中,经常有这样些特殊的类,必须保证它们在系统中只存在个实例,才能确 保它们的逻辑正确性、以及良好的效率。如何绕过常规的构造器,提供种机制来保证个类只创建一个实例?这应该是类设计者的责任,而不是类使用者的责任.结构图:加 munynce 二Singletonstatic InstanceO 0 SingletonOperatkn() GetSingletonData
2、Ostatic uniqueinstance singletonDaia意图:保证个类仅有一个实例,并提供个访问它的全局访问点。 GOF生活的例子:返回唯一实例适用性:(1 )当类只能有一个实例而且客户可以从个众所周知的访问点访问它时。(2)当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用个扩展的实例时。代码实现:(1 )单线程Singleton实现class SingleThread_Singletonprivate static SingleThread_Singleton instance = null; private SingleThread_Singleto
3、n()public static SingleThread_Singleton Instance( get (if (instance = = null)(instance = new SingleThread_Singleton();)return instance;)以上代码在单线程情况下不会出现任何问题。但是在多线程的情况下却不是安全的。如两个线程同时运行到if (instance = nuH)判断是否被实例化,个线程判断为True后, 在进行创建instance = new SingleThread_Singleton();之前,另个线程也判断(instance = = null),结
4、果也为 True.这样就就违背了 Singleton模式的原则(保证个类仅有一个实例)。怎样在多线程情况下实现Singleton?(2 )多线程Singleton实现:1 class MultiThread_Singleton2 3 private static volatile MultiThread_Singleton instance = null;4 private static object lockHelper = new object();5 private MultiThread_Singleton() 6 public static MultiThread_Singleton
5、Instance7 8 get9 10 if (instance = = null)11 12 lock (lockHelper)13 14 if(instance=null)15 16 instance = new MultiThread_Singleton();17 )18 19 )20 returninstance;21 )22 )23此程序对多线程是安全的,使用了一个辅助对象lockHelper,保证只有一个线程创建实例(如 果 instance 为空,保证只有一个线程 instance = new MultiThread_Singleton();创建唯一 的个实例)。(Double
6、Check)请注意个关键字volatile,如果去掉这个关键字,还是有可能发生线程不是安全的。volatile保证严格意义的多线程编译器在代码编译时对指令不进行微调。(3)静态Singleton实现3 class Static_Singleton4 5 publicstatic readonly Static_Singleton instance = new Static_Singleton();6 private Static_Singleton() 以上代码展开等同于1 class Static_Singleton2 public static readonly Static_Single
7、ton instance;4 static Static_Singleton()5 6 instance = new Static_Singleton();7 )8 private Static_Singleton() 9 )由此可以看出,完全符合Singleton的原则。优点:简洁,易懂缺点:不可以实现带参数实例的创建122 抽象工程模式(Abstract Factory)常规的对象创建方法:创建一个Road对象Road road = new Road();new的问题:实现依赖,不能应对“具体实例化类型”的变化。解决思路:封装变化点哪里变化,封装哪里潜台词:如果没有变化,当然不需要额外的封
8、装!工厂模式的缘起变化点在“对象创建”,因此就封装“对象创建”面向接口编程依赖接口,而非依赖实现最简单的解决方法:1 class RoadFactory2 public static Road CreateRoad()3 4 return new Road();5 )6 )7 创建一个Road对象8 Road road= roadFactory.CreateRoad();创建一系列相互依赖对象的创建工作:假设个游戏开场景:我们需要构造道路、房屋、地道,从林等等对象工厂方法如下:1 class RoadFactory2 (3 public static Road CreateRoad()4 (5
9、 return new Road();6 )public static Building CreateBuilding()8 9 return new Building();10 )11 public static TunnelCreateTunnel()12 13 return new Tunnel();14 )15 public static JungleCreateJungle()16 17 return new Jungle();18 )19 调用方式如下:1 Road road = RoadFactory.CreateRoad();Building building = RoadFa
10、ctory.CreateBuilding();4 Tunnel tunnel = Road Factory. CreateTunnel();5 Jungle jungle = RoadFactory.CreateJungle();如上可见简单工厂的问题:不能应对不同系列对象的变化。比如有不同风格的场景一对应不同风格的道路,房屋、地道,如何解决:使用面向对象的技术来封装变化点O动机(Motivate):在软件系统中,经常面临着系统相互依赖的对象的创建工作;同时,由于需求的变化, 往往存在更多系列对象的创建工作。如何应对这种变化?如何绕过常规的对象创建方法(new),提供种封装机制来避免客户 程序
11、和这种多系列具体对象创建工作的紧耦合?意图(I ntent):提供个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的 类。设计模式G0F 结构图(Struct):适用性:1 .一个系统要独立于它的产品的创建、组合和表示时。2 . 个系统要由多个产品系统中的一个来配置时。3 .当你要强调系列相关的产品对象的设计以便进行联合使用时。4 .当你提供个产品类库,而只想显示它们的接口不是实现时。生活例子:户,慢冲尔得”件。结构图代码实现:1 abstract class Abstract Factory2 (public abstract AbstractProductA CreateProdu
12、ctA();4 public abstract Abstract Products CreateProductB();5 )1 abstract class AbstractProductA2 public abstract void Interact (Abstract ProductB b);4 )1 abstract class AbstractProductB2 (3 public abstract void In teract (Abstract ProductA a);4 )1 class Client2 private AbstractProductA AbstractProdu
13、ctA;4private AbstractProductB AbstractProductB;678910111213141512345678910111234567891011Abstract ProductA = factory .CreateProductA();Abstract Products = factory.CreateProductB();)public void Run()(Abstract Products. I nteract( Abstract ProductA);Abstract ProductA. I nt eract( Abstract Products);)c
14、lass Co n cr et e Fact o r y 1: Ab st r act Fact o r y(public override AbstractProductA CreateProductA()(return new ProductAI ();public override Abstract Products CreateProductB() (return new ProductBI ();)class ConcreteFactory2: Abstract Factory(public override AbstractProductA CreateProductA() (re
15、turn new ProdcutA2();)public override Abstract Products CreateProductB() (return new ProductB2();) 1 class Product A1: Abstract Product A3 public override void Interact(AbstractProductB b)4 5 Console.WriteLine(this.GetType().Name + Minteract with + b.GetType().Name);6 )7 )1 class ProductBI: Abstract
16、ProductB2 3 public override void lnteract(AbstractProductA a)4 5 Console.WriteLine(this.GetType().Name + interact with + a.GetType().Name);6 )7 1 class ProdcutA2: AbstractProductA2 (3 public override void Interact (Abstract ProductB b)4 5 Console.WriteLine(this.GetType().Name + interact with + b.Get
17、Type().Name);6 )7 1 class ProductB2: AbstractProductB2 (3 public override void Interact(AbstractProductA a)4 5 Console.WriteLine(this.GetType().Name + interact with + a.GetType().Name);6 )7 )1 public static void Main()2 (3 / AbstractfactorylAbstract Factory factoryl = new ConcreteFactoryl ();5 Clien
18、t c1 =newClient(factory1);6 c1 .Run();7 Abstractfactory28 Abstract Factoryfactory2 = new ConcreteFactory2();9 Client c2 =newClient(factory2);10 c2.Run();11 Abstract Factory 注意的几点:如果不存在”多系列对象创建的需求变化,则没必要应用Abstract Factory 模式,静态工厂方法足矣。系列对象”指的是这些对象之间有相互依赖、或作用的关系。例如游戏开发 场景中的道路与房屋依赖,“道路与地道的依赖。Abstract Fa
19、ctory模式主要在于应对”新系歹的需求变动。其缺点在于难以 应对新对象”的需求变动。Abstract Factory模式经常和Factory Method模式共同组合来应对“对 象创建”的需求变化12 .3建造者模式(Builder)Builder模式的缘起:假设创建游戏中的个房屋House设施,该房屋的构建由儿部分组成,且各个部分富于变 化。如果使用最直观的设计方法,每个房屋部分的变化,都将导致房屋构建的重新修正一 动机(Motivation):在软件系统中,有时候面临个“复杂对象”的创建工作,其通常由各个部分的子对象用一定 办法构成;由需求的变化,这个复杂対象的各个部分经常面临着剧烈的变
20、化,但是将它们组合 到起的算法却相对稳定。如何应对种变化呢?如何提供种封装机制来隔离出复杂对象的各个部分的变化,从而 保持系统中的稳定构建算法不随需求的改变而改变?意图(Intent):将一个复杂对象的构建其表示相分离,使得同样的构建过程可以创建不同的表示。设计模式GOF结构图(Struct):DirectorBuilder+Construct()-BuildPart()Fetch Item in Structure build.BuildPart()ConcreteBuilder*BuildPart()*GctRcsult()aDirectoraConcreteBuilder协作(Colla
21、borations):aClient生活中的例子:new DireclorfaConcreteBuikJer)ConstructOBuildPadAOI new ConcreteButldefBuikJPadBOBuiklParlCoGetResultOMXMM适用性:1 .当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。2 .当构造过程必须允许被构造的对象有不同的表示时。实例代码:Builder 类:1 public abstract class Builder2 3 publicabstractvoidBuildDoor();4 publicabstractvoidBu
22、ildWall();5 publicabstractvoidBuildWindows();6 publicabstractvoidBuildFloor();7 publicabstractvoidBuildHouseCeilingO;89 public abstract House GetHouse();10 )Director类:这一部分是组合到起的算法(相对稳定)。1 public class Director2 3 public void Construct(Builder builder)4 (5 builder.BuildWall();6 builder. BuildHouseCei
23、lingO;7 builder.BuildDoor();8 builder.BuildWindows();9 builder.BuildFloor();10 )11 )ChineseBuilder 类1 public class ChineseBuilder: Builder2 3 private House ChineseHouse = new House();4 public override void BuildDoor()Console.WriteLine(this Door *s style of Chinese);7 )8 public overridevoid BuildWall
24、()9 10 Console.WriteLine(this Wall s style of Chinese,);11 )12 public overridevoid BuildWindows()13 14 Console.WriteLine(this Windows *s style of Chinese);15 )16 public overridevoidBuildFloor()17 18 Console.WriteLine(this Floor *s style of Chinese);19 20 public overridevoidBuildHouseCeiling()21 Cons
25、ole.WriteLine(this Ceiling *s style of Chinese);23 )24 public override House GetHouse()25 26 return ChineseHouse;27 )28 )RomanBuilder 类:1 class RomanBuilder:Builder2 3 private House RomanHouse = new House();4 public overridevoidBuildDoor()5 6 Console.WriteLine(this Door *s style of Roman);7 8 public
26、 overridevoidBuildWall()9 (10 Console.WriteLine(this Wall *s style of Roman);12 public override void BuildWindows()13 14 Console.WriteLine(this Windowss style of Roman);15 )16 public overridevoidBuildFloor()17 18 Console.WriteLine(this Floor ,s style of Roman);19 )20 public overridevoidBuild Hou seC
27、eili ng ()21 22 Console.WriteLine(this Ceilings style of Roman);23 )24 public override House GetHouse()25 26 return RomanHouse;27 )28 )ChineseBuilder fll RomanBuilder这两个是:这个复杂对象的两个部分经常面 临着剧烈的变化。1 public class Client2 3 public static void Main(string args)4 (5 Director director = new Director();67 Bu
28、ilder instance;89 Console.WriteLine(Please Enter House No:);1011 string No = Console. Read Li ne();1213 string houseType = ConfigurationSettings.AppSettingsNo + No;15instance = (Builder) Assem bly.Load(* House). Createlnstance(M House.* + houseType);1617di rector. Con struct (instance);1819 House ho
29、use= instance.GetHouse();20 house.Show();2122 Console.ReadLine();23 )24 )1 2 3 4 5 6 7 Builder模式的几个要点:Builder模式主要用于“分步骤构建一个复杂的对象”。在这其中“分步骤”是 个稳定的乘法,而复杂对象的各个部分则经常变化。Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动。其缺点在于 难以应对“分步骤构建算法”的需求变动。Abstract Factory模式解决“系列对象”的需求变化,Builder模式解决“对 象部分”的需求变化。Builder械通常和Composite模式
30、组合使用124工厂方法模式(Factory Method)耦合关系:耦合关系直接决定着软件面对变化时的行为-模块与模块之间的紧耦合使 得软件面对变化时,相关的 模块都要随之更改-模块与模块之间的松耦合使 得软件面对变化时,一些模 块更容易被替换或者更改, 但其他模块保持不变动机(Motivation):在软件系统中,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但它却有 比较稳定的接口。如何应对这种变化呢?提供种封装机制来隔离出这个易变对象的变化,从而保持系统中 其它依赖的对象不随需求的变化而变化。意图(I ntent):定义个用户创建对象的接口,让子类决定实例哪个类。Factory
31、 Method使个类的实 例化延迟到子类。设计模式GOF生活实例:结构图(Struct):玩具马模具适用性:1 .当一个类不知道它所必须创建的对象类的时候。2 .当个类希望由它子类来指定它所创建对象的时候。3 .当类将创建对象的职责委托给多个帮助子类中的某个,并且你希望将哪个帮助子类是代 理者这一信息局部化的时候。实例代码:CarFactory 类:1 public abstract class CarFactory2 (3 public abstract Car CarCreate();4 )Car 类:1 public abstract class Car2 (public abstrac
32、t void StartUp();4 public abstract void Run();5 public abstract void Stop();67 HongQiCarFactory 类:1 public class HongQiCarFactory:CarFactorypublic override Car CarCreate()4 5 return new HongQiCar();6 )7 )BMWCarFactory 类:1 public class BMWCarFactory:CarFactory2 (3 publicoverride Car CarCreate()4 5 re
33、turn new BMWCar();6 )7 )HongQiCar 类:1 public class HongQiCar:Car2 3 publicoverridevoidStartUp()4 (5 Console.WriteLine(Test HongQiCar start-up speed!);6 )7 publicoverridevoidRun()8 9 Console.WriteLine(The HongQiCar run is very quickly!);10 )11 public override void Stop()12 13 Console.WriteLine(The sl
34、ow stop time is 3 second );14 )15 )BMWCar 类:1 public class BMWCar:Car2 3 public override void StartUpOConsole.WriteLine(MThe BMWCar start-up speed is very quickly);6 )7 public override voidRun()8 9 Con sole. Writ eLine( The BMWCar run is quitely fast and safe!*);10 )11 public override void Stop()12
35、13 Console.WriteLine(The slow stop time is 2 second);14 )15 )app.config1 2 3 4 5 odd key=No2 value= BMWCarFactory/6 7 Program 类:1 class Program3 static void Main(string args)5 Console.WriteLine(Please Enter Factory Method No:);6Console.WriteLine(*);7Console.WriteLine(noFactory Method);Console. Write
36、Line(1HongQiCarFactory);9Console.WriteLine(2BMWCarFactor);10Console.WriteLine(*);11int no= lnt32.Parse(Console.ReadLine().ToString();12string factoryType= ConfigurationManager.AppSettingsNo+ no;13/CarFactory factory = new HongQiCarFactory();14CarFactory factory = (CarFactory)Assembly.Load(FactoryMeh
37、tod).Createlnstance(HFactoryMehtod. + factoryType);15 Car car= factory.CarCreate();16 car.StartUp();17 car.Run();18 car.Stopf);1920 )21 Factory Method模式的几个要点:Factory Method模式主要用于隔离类对象的使用者和貝体类型之间的耦合关系。面对个经常 变化的具体类型,紧耦合关系会导致软件的脆弱。Factory Method模式通过面向对象的手法,将所要创建的R体对象工作延迟到子类,从而实现 种扩展(而非更改)的策略,较好地解决了这种紧耦
38、合关系。Factory Mehtod模式解决单个对象”的需求变化,AbstractFactory模式解决系歹对象的需求变化,Builder模式解决“对象部分”的需求变化125 原型模式(Prototype)依赖关系倒置:抽象不应该依赖于实现细节,实现细节应该依赖于抽象。抽象A直接依赖于实现细节b抽象A依赖于抽象B,实 现细节b依赖于抽象B实现细节b抽象A抽象B实现细节b动机(Motivate):在软件系统中,经常面临着“某些结构复杂的对象的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。如何应对这种变化?如何向“客户程序(使用这些对象的程序)隔离出“这
39、些易变对象”,从 而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?意图(Intent):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。设计模式GOF结构图(Struct):生活例子:适用性:1 .当一个系统应该独立于它的产品创建,构成和表示时;2 .当要实例化的类是在运行时刻指定时,例如,通过动态装载;3 .为了避免创建一个与产品类层次平行的工厂类层次时:4 .当个类的实例只能有几个不同状态组合中的种时。建立相应数目的原型并克隆它们 可能比每次用合适的状态手工实例化该类更方便一些。示意性代码例子:1 public abstract class NormalActor
40、2 3 public abstract NormalActor clone();4 )1 public class NormalActorA:NormalActor2 (3 public override NormalActor clone()4 5 Con sole. Writ eLine( Norm al Act or A is call);6 return (NormalActor)this.MemberwiseClone();78 9 )1 public class NormalActorB :NormalActor2 (3 public override NormalActor cl
41、one()4 5 Con sole. WriteLine( NormalActorB was called);6 return (NormalActor)this.MemberwiseClone();78 )9 )public class GameSystempublic void Run(NormalActor normalActor)NormalActor normalActorl = norm al Actor. clone();NormalActor normalActor2 = norm al Act or. cion e();NormalActor normalActor3 = n
42、ormalActor.clone();NormalActor normalActor4 = normalActor.clone();NormalActor normalActor5 = normalActor.clone();)classProgram(static void Main(string args)(GameSystem gameSystem = new GameSystem();gam eSy stem. Run (new NormalActorA();) )如果又需要创建新的对象(flyActor),只需创建此抽象类,然后具体类进行克隆。public abstract class FlyActor (public abstract FlyActor clone();public class FlyActorB: FlyActor(/ /Z浅拷贝,如果用深拷贝,可使用序列化/ / public override FlyActor clone()return (FlyActor)this.MemberwiseClone();)此时,调用的Main。函数