23种设计模式含例题_第1页
23种设计模式含例题_第2页
23种设计模式含例题_第3页
23种设计模式含例题_第4页
23种设计模式含例题_第5页
免费预览已结束,剩余53页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、创建型模式:这里指出了关联的product!所以说,一个Factory和一个Product是一一对应的关系。Factorymethod:定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类接口函数:Creator:FactoryMethod:纯虚函数,由派生类实现,创建出对应的Product.由相应的Factory派生类来生成Product的派生类,一个Factory和一个Product是一一对应的关系。也就是说如果要新增一种Product那么也要对应的新增一个Factory。每个factory负责自身产品创建的策略,保证各自;,的灵活性

2、,符合单一职责原则。Abstractfactory:AbstractFactory模式是为创建一组(多类)相关或依赖的对象提供创建接口,而Factorymethod是为一类对象提供创建接口或延迟对象的创建到子类中实现。AbstractFactory模式通常都是使用Factorymethod实现Builder模式是基于这样的一个情况:一个对象可能有不同的组成部分,这几个部分的创建具有多样性,但是各个部分之间装配的方式是一致的.Director:Construct函数中固定了各个组成部分的装配方式,而装配用到的具体组成部分由Builder的派生类实现.多态的零件制造、一致的装配过程(多态的)各零件

3、组成了product装配方式:完成各组件间的关联、组装I-*接口:Builder:BuildPart()是对l个对象不同部分的构建函数接口,Builder的派生类来具体实现Director:Construct()通过调用上面的接口函数完成各个部分的装配实现:Builder模式基于以下几个面向对象的设计原则:1)把变化的部分提取出来形成一个基类和对应的接口函数2)采用聚合的方式聚合了会发生变化的基类,就是这里Director聚合了Builder类的指针.适用于以下情况:1)当创建复杂对象的算法应该独立于该对象的组成部分的装配方式时2)当构造过程必须允许被构造的对象有不同的表示时Prototype

4、:Prototype模式其实就是常说的虚拟构造函数,通过不同派生类的Clone()完成虚拟构造函数的效果CliiOperaloflO9DfDtOtVP?APrtnaiypeCtonef浅克隆”&深克隆Ip-pOtot/peMJkJREfConcm怩FromW口。1CkJiet;pcorKteieynjtotype2Ctoflftl)9Jreturn8科SC#rorumcflpyjewlf接口函数:Prototype:Clone():纯虚函数,根据不同的派生类来实例化创建对象Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点X(WfTiun咫uMn备门心Srnglstain

5、statelnsTanc()AS扑9他何卜。*亡GetShgietonDaiaf)jtiteuniqueIn叫日ngsnirinnUeiaSingleton模式其实是对全局静态变量的一个替代策略,在C+中是这样实现的:1)提供一个类的静态成员变量,类的静态成员变量对于一个类的所有对象是惟一的2)提供访问这个静态成员变量的静态成员函数,对类的所有对象而言也是惟一的.结构性模式:Adapt模式使得原本由于接口不兼容而不能一起工作的那些类可Adapter:将一个类的接口转换成客户希望的另外一个接口O以一起工作。接口转换)C油ntJargelAdaptsAdaplar把完成同样的功能但是接口不能兼容的

6、类,桥接在一起;这个模式使得复用旧的接口成为可能Target类和用户接口,通过Adapter桥接后,幕后变为Adaptee类实现BridgeImplementor:OperationImpl():定义了为实现Abstraction需要的基本操作,由派生类具体实现。在Bridge模式中,系统被分为两个相对独立的部分,Abstraction是抽象部分,Implementor是实现部分,这两个部分可以互相独立地进行修改。当需要从Abstraction派生一个子类时,不再通过继承方式实现,而是只需在Implementor中添加一个子类而已(;右边的这颗类树开始变得扁平.),Abstraction无需任

7、何变化。风格变得elegant!尽量使用组合/聚合关系而不是继承关系:favorcompositionoverInheritanceBridge的实现方式和Builder十分相近,本质上是一样的,只是封装的内容不一样.共同点:抽象出来一个基类,这个基类里面定义了共性行为,形成接口函数聚合一个基类的指针,把这个指针的使用封装在一个函数中Builder封装了不同的生成组成部分的方式,而Bridge封装了不同的实现方式.Composite:Composite使得用户对单个对象和组合对象的使用具有一致性。(;图元的组合处理、文件和文件夹的复制)component为基类,leaf为单个对象,compos

8、ite为组合对象,内含一个component数据结构(比如:array、tree);Composite模式是为解决组件之间的递归组合提供了很好的解决办法接口函数:Operatation():共有的行为,由各个子类具体实现.含有子组件的类:Add(),Remove(),GetChild()应用情况:想要表示对象的整个或部分的层次结构需要客户端忽略复合对象和单个对象之间的差异结构可以具有任何级别的复杂性而且是动态的Decorator:动态地给一个对象添加一些额外的“装饰”。Decorator模式比生成子类更为灵活,它不是通过继承实现的,而是通过组合。通过继承的方式会带来系统的复杂性,因为继承的深度

9、会变得很深。动态的添加装饰,提供了比继承更有弹性的替代方案接口函数:Operation():Decorator类对component类的装饰,是通过operation。的多态调用实现的Decorator的派生类装饰ConcreateComponent类的对象.实现要点是:Decorator和ConcreateComponent者B继承自Component,;Decorator维护了一个指向Component的指针,从而可以实现对Operation()的动态调用.优点:1、使得整个类树变得更扁平化;2、动态,透明”的方式来添加职责,使得父子类间的关系更简约化应用情况:想要在单个对象中动态、透明的

10、添加装饰,这样不会影响其他对象;想要在以后可能要修改的对象中添加职责无法通过静态子类化实现扩展时Fa?ade:Facade外观模式为子系统中的各类(或结构与方法)提供一个简明一致的界面,隐藏子系统的复杂性,使子系统更加容易使用。为子系统中的一组接口所提供的一个一致的界面(在日常开发中,早已大量应用)Facade类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与Facade对象打交道,而不需要与子系统内部的很多对象打交道。适用情况:为一个复杂子系统提供一个简单接口。提高子系统的独立性。在层次化结构中,可以使用Facade模式定义系统中每一层的入口。FlyWeight:Flyweight(享

11、元模式)在大量使用可被共享的对象的时候经常使用。当需要一个对象的时候,先去查询是否已经存在了,如果没有就生成,有的话就直接使用.注意共性、个性的协调处理FlyweightFactory是个对象构造工厂,拥有一个对象池(list实现)。当Client需要一个对象时候就会向FlyweightFactory发出tt求GetFlyweight(),GetFlyweight()会遍历对象池中的对象,如果已经存在则直接返回否则创建一个新的对象返回。含有缓冲池,记录内容状态内部对象,可共享(外部对象,不可共享通过共享一个接口来避免使用多个具有相同信息的实例所带来的开销。避免大量相同对象造成的开销,通常是内存

12、消耗各对象将共性进行共享,同时又保留自己的个性Proxy:为对象提供一种代理以控制对这个对象的访问。至少在以下几种情况下可以用Proxy模式:RemoteProxy:为网络上的对象创建一个局部的本地代理,比如要操作一个网络上的一个对象(网络性能不好的时候,问题尤其突出),我们将这个操纵的过程交给一个代理去完成;VirtualProxy:创建开销大的对象时候,比如显示一幅大的图片,我们将这个创建的过程交给代理去完成;ProtectionProxy:对对象进行控制访问的时候,比如论坛中不同权限的用户将获得不同层次的操作权限,我们将这个工作交给一个代理去完成在特定情景下,满足某不条件时,再调用Rea

13、lSubject事前处理:权限、条件、拦截nea-Reqi悟或0:Subject.Request():定义了Proxy和RealSubject的公有接口,这样就可以在任彳需要使用到RealSubject的地方都使用Proxy代理实现.Proxy其实是基于这样一种时常使用到的技术-某个对象直到它真正被使用到的时候才被初始化,在没有使用到的时候就暂时用Proxy作一个占位符.这个模式实现的要点就是Proxy和RealSubject都继承自subject,确保了他们有共同的接口。优点:远程代理可以隐藏对象位于不同的地址空间的事实虚拟代理可以执行优化操作,例如根据需要创建一个对象注意:Fa?ade模式

14、注重简化接口,Adapter模式注重转换接口,Bridge模式注重分离接口(抽象)与其实现,Decorator模式注重稳定接口的前提下为对象扩展功能。行为性模式ChainofResponsibilityChainofResponsibility模式描述了这样一类问题:将可能处理一个请求的对象联接成一个链,并将请求在这个链上传递,直到有对象处理该请求。接口:Handler.HandleRequset()处理请求,同时有一个指针successor,指向后继对象。ConcreteHandler将自己的后继对象记录在自己的后继指针中,当一个请求到来时,ConcreteHandler会先检查看自己有没有

15、匹配的处理程序,如果有就自己处理,否则传递给它的后继。举例:消息的发送者并不MFC提供了消息的链式处理策略,处理消息的请求将沿着预先定义好的路径依次进行处理。知道该消息最后是由那个具体对象处理的,但是结果是该消息被某个对象处理了。优点:降低了请求的发送者和接收者之间的耦合关系增加了为对象指定责任的灵活性适用情况:多个对象可以处理一个请求,而其处理器确实未知的在不确切指定处理对象的情况下,向其中的一个发送请求动态指定能够处理请求的对象集(链可能是个链表,也可能是个tree、graph)把响应函数放在这里,Command激活后,会自动调用CommandCommand模式通过将命令封装到Comman

16、d对象中,将接“者封装到Receiver中。(;callback函数)CiiwlAarGelbrate(J表示层和数据层之间的分离Observer模式定义的是一对多的关系,一个Subject对应多个Obesrver。当Subject的状态发生变化时,通知与之对应的所有Obesrver也去相应更新,同时支持动态的注册或注销Observer对象。要点:Subject内一般采用链表指针来关联Observer接口:Subject.Attach():对Observer的注册;Subject.Detach():对Observer的注销;Subject.Notify():通知所有关联Observer更新举例

17、:在MFC中,Doc/View实现了MVC的框架结构。当document改变时,对应多种风格的view都相应变更。Observer模式是应用最多、影响最广的模式之一.适用情景:对一个对象的修改涉及对其他对象的修改,且不知有多少对象需要相应修改State:状态驱动一个对象在其内部状态改变时,改变它的行为记录状态:对应一个state子类对象Context调用Request(),在不同的内部状态下对应不同的行为。每个ConcreteState对应一个具体的状态。传统方式是采用switch-case语句进行处理的,其问题是:分支过多,而且加入一个新的状态就需要对原来的代码进行编译。State模式下,对

18、这些不同的状态处理进行了封装,当State.Handle()响应处理时,会自动迁移到另一种状态,即状态的切换责任交给了具体的状态类ConcreteState去负责。举例:有限状态自动机(FSM),随着当前状态的不同,对输入有不同的响应。适用情景:对象的行为依赖于其状态,并且该对象必须在运行时根据其状态动态改变其行为Strategy定义一系列的算法,并且使它们可相互替换.本模式使得算法可独立于使用它的客户而变化解析:Strategy中封装了算法的具体实现。Context中存储一个strategy指针,选择执行采用哪个算法。优点:另一种子类化方法在类自身中定义了每一个行为,这样就减少了条件语句更容

19、易扩展模型。在不对应用程序进行代码修改的情况下,使该模式具有新的行为适用情况:许多相关类只是行为方面有所区别需要算法的不同变体State模式和Strategy模式在图示上有很多相似的地方,需要说明的是两者的思想都是一致的,只不过封装的东西不同:State模式封装的是不同的状态,而Stategy模式封装的是不同的算法.Templatemethod:骨架固定、细节重载定义一个操作中的算法的骨架,而将各步骤的实现延迟到子类中。接口:1) AbstractClass.TemplateMethod():定义算法的骨架2) AbstractClass.PrimitiveOperation():算法各步骤的

20、实现Template模式是采用继承的方式,将算法的轮廓放在抽象基类中,但是算法每一步具体的实现留给了派生类.使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。Template和Strategy解决的是类似的问题。但是Template模式是采用继承方式,而Strategy是采取组合的方式Visitor双重分派当一组具有固定数据结构(比如一个list、或array)的节点需要多种处理能力,且处理能力可扩展。即在不改变原来类结构(节点)的基础上增加新功能。1)访问者角色(Visitor):为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送请求给visito

21、r的具体元素角色。这样访问者就可以通过该元素的特定接口直接访问它。2)具体访问者角色(ConcreteVisitor):实现每个由访问者角色(Visitor)声明的操作。3)元素角色(Element):定义一个Accept操作,它以一个访问者为参数。4)具体元素角色(ConcreteElement):实现由元素角色提供的Accept操作。5)对象结构角色(ObjectStructure):这是使用访问者模式必备的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个复合(组合模式)或是一个集合,如一个列表或一个无序集合在Visitor模式中Acce

22、pt()操作是一个双分派的操作。具体调用哪一个具体的Accept()操作,有两个决定因素:Element的类型。因为Accept()是多态的操作,需要具体的Element类型的子类才可以决定到底调用哪一个Accept()实现;Visitor的类型。Accept()操作有一个参数(Visitor*vis),要决定了实际传进来的Visitor的实际类别才可以决定具体是调用哪个VisitConcrete()实现。在不改变各元素类的前提下定义彳用于这些元素的新操作。VisitorJ模式使得增加新的操作很容易适用情景:Visitor模式适用于数据结构相对稳定的系统(比如一个数组)、官杷数据结构和作用于数

23、据结构匕的操作之间的耦合降低,使得操作可以相对自由地演化.数据结构的每一个结点都可以接受一个访问者的调用,此结点向访问者对象传入结点对象,而访问者对象则反过来执行结点对象的操作讨论:Strategy模式和Template模式实际是实现一个抽象接口的两种方式:继承和组合之间的区别。要实现一个抽象接口,继承是一种方式:我们将抽象接口声明在基类中,将具体的实现放在具体子类中。组合(委托)是另外一种方式:我们将接口的实现放在被组合对象中,将抽象接口放在组合类中。这两种方式各有优缺点,先列出来:1)继承:优点1)易于修改和扩展那些被复用的实现。缺点1)破坏了封装性,继承中父类的实现细节暴露给子类了;2)

24、白盒”复用,原因在1)中;3)当父类的实现更改时,其所有子类将不得不随之改变4)从父类继承而来的实现在运行期间不能改变(编译期间就已经确定了)。2)组合优点1)黑盒”复用,因为被包含对象的内部细节对外是不可见的;2)封装性好,原因为1);3)实现和抽象的依赖性很小(组合对象和被组合对象之间的依赖性小);4)可以在运行期间动态定义实现(通过一个指向相同类型的指针,典型的是抽象基类的指针)。缺点1)系统中对象过多。从上面对比中我们可以看出,组合相比继承可以取得更好的效果,因此在面向对象的设计中的有一条很重要的原则就是:优先使用(对象)组合,而非(类)继承(FavorCompositionOverI

25、nheritance)。实际上,继承是一种强制性很强的方式,因此也使得基类和具体子类之间的耦合性很强。例如在Template模式中在ConcreteClass1中定义的原语操作别的类是不能够直接复用(除非你继承自AbstractClass,具体分析请参看Template模式文档)。而组合(委托)的方式则有很小的耦合性,实现(具体实现)和接口(抽象接口)之间的依赖性很小,例如在本实现中,ConcreteStrategyA的具体实现操作很容易被别的类复用,例如我们要定义另一个Context类AnotherContext,只要组合一个指向Strategy的指针就可以很容易地复用ConcreteStr

26、ategyA的实现了。我们在Bridge模式的问题和Bridge模式的分析中,正是说明了继承和组合之间的区别。请参看相应模式解析。举例:factorymethod例题:生产洗发水廉*水CLEARClKt,*Shwnpoc用走/producefCLAR方建I;pfoduc(fHAZE叫s)LCl,*Shvnpaoe那强上皿B京电pradix。-:HA2EUNEHAZEUNtfrt&ry0M4Factory-方法V。卅w5htmpo。tflLLTCLEARfimryci,*FKtofy-趣cftJiteShBmipoci&rfa版Attractl对去VcrcAtrShdiripGOabstract

27、classShampoo/抽象的洗发水类(publicabstractvoidproduce();)classHAZELINE:Shampoo/“夏士莲”洗发水,继承抽象洗发水类(publicoverridevoidproduce()(Console.WriteLine(夏土莲洗发水);)classCLEAR:Shampoo/“清扬”洗发水,继承抽象洗发水类(publicoverridevoidproduce()(Console.WriteLine(清扬洗发水);)abstractclassFactory抽象的洗发水工厂类(publicabstractShampoocreateShampoo(

28、);classHAZELINEfactory:Factory/“夏士莲”洗发水工厂,继承抽象洗发水工厂(publicoverrideShampoocreateShampoo()(Console.Write(生产:);returnnewHAZELINE();classCLEARfactory:Factory/清扬洗发水工厂,继承抽象洗发水工厂(publicoverrideShampoocreateShampoo()(Console.Write(生产:);returnnewCLEAR();staticvoidMain(stringargs)(/实例化“夏士莲”工厂/“夏士莲”工厂只创造夏士莲洗发水

29、/实例化“清扬”工厂/“清扬”工厂只创造清扬洗发水Shampooshampoo;Factoryfactory=newHAZELINEfactory();shampoo=factory.createShampoo();duce();factory=newCLEARfactory();shampoo=factory.createShampoo();duce();abstractfactory有两个车间,其中一个车间用以生产餐具,一个车间用以生产相应的食物。当消费者消费时,只需要向相应的具体工厂请求具体餐具和具体食物便可以使用餐具消费食物。3个具体工厂每个

30、具体工厂生产出来的具体产品根据不同工厂的不同各不相同,但是客户使用产品的方法是一致的。比如客户在得到餐具和食物之后,两者的搭配是固定的(使用汤匙喝牛奶,使用刀子切面包)。在本例子中有AKitchenBKitchenBKitchen,分别生产牛奶和汤匙、面包和刀、肉和叉子KetchniFactQfy*SFd0:Fgd*QTablWw*AKjetcheniKAR+gkiTool0:Siring-1ApackageabstractFactory;02.03.publicinterfaceKitchenFactory04.05.06.07.08.09.10.publicFoodgetFood();15

31、.publicinterfaceTableWarepublicTableWaregetTableWare();11 .抽象餐具的接口定义如下所示:12 .13 .packageabstractFactory;14 .16.17. publicStringgetTool();18.19. 20.21. 抽象事物的接口定义如下所示:22.23. packageabstractFactory;24.25.publicinterfaceFood26.27. publicStringgetEatable();28.29. 30.31. 而具体的实现也非常简单,以AKitchen为例子32.33. 具体工

32、厂AKitchen的定义如下所示;34.35. packageabstractFactory;36.37. publicclassAKitchenimplementsKitchenFactory1.publicFoodgetFood()returnnewMilk();1. )52.53.54.publicTableWaregetTableWare()returnnewSpoon();55 .具体餐具(spoon)的定义如下所示:56 .57 .packageabstractFactory;58 .59 .publicc

33、lassSpoonimplementsTableWare6.67.)68.publicStringgetTool()returnspoon;69 .具体食物(milk)的定义如下所示:70 .71 .packageabstractFactory;72 .73. publicclassMilkimplements74.75. publicStringgetEatable()76.77. returnmilk;78.79. )80.Food81.)82.83.客户端的定义如下:84.85. packageabstractFactory;86.87. publi

34、cclassClient88.89. publicvoideat(KitchenFactoryk)90.91. System.out.println(Apersoneat+k.getFood().getEatable92.93. +with+k.getTableWare().getTool()+!);94.95. )96.97. publicstaticvoidmain(Stringargs)98.99. Clientclient=newClient();100.101. KitchenFactorykf=newAKitchen();102.103. client.eat(kf);104.()

35、014.115. kf=newBKitchen();client.eat(kf);kf=newCKitchen();client.eat(kf);builder模式模拟一个电脑生产、装配的过程:1 ./首先是一个建造工具(builder)接口2 .publicinterfacebuilder3.4.5.voidBuildChassis();/voidBuildKboard();/主机键盘6.voidBuildMonitor();/显示器7.voidBuildMouse();/鼠标8.computergetcomputer(

36、);/返回产品9.1./建造工具的具体建造方式:implementsbuilder2.publicclassConcreteBuilder3.4.privateStringChassis;5.privateStringMonitor;6.privateStringKboard;7.8.privateStringMouse;Override9.publicvoidBuildChassis()10./11.System.out.println(生产主机);12.Chassis=MAC主机;13.14.15.Override16.publicvoidBuildKboard()17./18.19.Sy

37、stem.out.println(生产键盘);Kboard=MAC键盘;20.21.22.Override23. publicvoidBuildMonitor()24. /25. System.out.println(生产显示器);26. Monitor=MAC显示器;27. 28.29. Override30. publicvoidBuildMouse()31. /32. System.out.println(生产鼠标);33. Mouse=MAC鼠标;34. 35.36. Override37. publiccomputergetcomputer()38. /39. System.out.

38、println(电脑生产完成);40. computerc=newcomputer。;41. c.setJianpan(Kboard);42. c.setShubiao(Mouse);43. c.setXianshiqi(Monitor);44. c.setZhuji(Chassis);45. returnc;46. 47.48. 1.2. publicclassDirector3.4. privatebuilderbuilder;5. publicDirector(builderbuilder)6. 7. this.builder=builder;8. 9.10. /将零件主机显示器键盘鼠标

39、组成复杂的对象11. /组装电脑的过程12. publicvoidconstruct()13. 14. builder.BuildChassis();15. builder.BuildMonitor();16. builder.BuildMouse();17. builder.BuildKboard();18. 19. publicclasscomputer(privateStringChassis;privateStringMonitor;privateStringKboard;publicvoidsetZhuji(StringChassis)publicvoidsetXianshiqi(S

40、tringMonitor)publicvoidsetJianpan(StringKboard)publicvoidsetShubiao(StringMouse)privateStringMouse;this.Chassis=Chassis;this.Monitor=Monitor;this.Kboard=Kboard;this.Mouse=Mouse;publicvoidinfo()System.err.println(String.format(我的配置如下+,主机:s显示器:%s键盘:%s鼠标:s,Chassis,Monitor,Kboard,Mouse);1. publicclassge

41、tcomputer2.3. publicstaticvoidmain(Stringargs)4. ConcreteBuilderbuilder=newConcreteBuilder();5. Directordirector=newDirector(builder);6. director.construct();7. computerc=builder.getcomputer();8. ();9. 10. singleton模式classSingleton:private:Singleton();staticSingleton*m_pInstance;public:staticS

42、ingleton*GetInstance()if(m_pInstance=NULL)m_pInstance=newSingleton();returnm_pInstance;Bridge模式生活中的一个例子:就拿汽车在路上行驶的来说。即有小汽车又有公共汽车,它们都不但能在市区中的公路上行驶,也能在高速公路上行驶。这你会发现,对于交通工具(汽车)有不同的类型,然而它们所行驶的环境(路)也在变化,在软件系统中就要适应两个方面的变化?怎样实现才能应对这种变化呢?概述:在软件系统中,某些类由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种多维度的变化”?如何利用面向对象的技术来使得该类能够轻

43、松的沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。意图:将抽象部分与实现部分分离,使它们都可以独立的变化。设计模式GOF传统的做法:通过类继承的方式来做上面的例子;先看一下类结构图:所有路的基类d口3-方法*Eun高速公路市区中的街道代码实现:1namespaceCarRunOnRoad2口日3|/路的基类;4publicclassRoad59由61publicvirtualvoidRun()7门中8 IConsole.WriteLine(在路上);9 )10 I)11 高速公路;12 IpublicclassSpeedWay:Road13=:14 publicov

44、erridevoidRun()(Console.WriteLine()19 /市区街道;20 IpublicclassStreet:Road21 门口(22 IpublicoverridevoidRun()24 l_LConsole.WriteLine(市区街道);25 )26 )27 /小汽车在高速公路上行驶;28 IpublicclassCarOnSpeedWay:SpeedWay29 口口(30 IpublicoverridevoidRun()31 口(32 Console.WriteLine(小汽车在高速公路上行驶);33 I)34 )35 /公共汽车在高速公路上行驶;36 Ipubl

45、icclassBusOnSpeedWay:SpeedWay37的n38publicoverridevoidRun()39的40 Console.WriteLine(公共汽车在高速公路上行驶);41 )42 )43444546474849505152535455|_I卜7|_卜!78555960/小汽车在市区街道上行驶;publicclassCarOnStreet:Street(publicoverridevoidRun()(Console.WriteLine(汽车在街道上行驶);/公共汽车在市区街道上行驶;publicclassBusOnStreet:Street(publicoverride

46、voidRun()(Console.WriteLine(公共汽车在街道上行驶);客户端调用1staticvoidMain(stringargs)(/小汽车在高速公路上行驶CarOnSpeedWayCar=newCarOnSpeedWay();Car.Run();6 _7 Console.WriteLine(=);89 /公共汽车在街道上行驶10 IBusOnStreetBus=newBusOnStreet();11 Bus.Run();1213 IConsole.Read();14 L缺点:但是我们说这样的设计是脆弱的,仔细分析就可以发现,它还是存在很多问题,首先它在遵循开放-封闭原则的同时,

47、违背了类的单一职责原则,即一个类只有一个引起它变化的原因,而这里引起变化的原因却有两个,即路类型的变化和汽车类型的变化;其次是重复代码会很多,不同的汽车在不同的路上行驶也会有一部分的代码是相同的;再次是类的结构过于复杂,继承关系太多,难于维护,最后最致命的一点是扩展性太差。如果变化沿着汽车的类型和不同的道路两个方向变化,我们会看到这个类的结构会迅速的变庞大。应用设计模式桥接模式(Bridge)来做;先看一下类结构图:市区正由Emn陆hrAbstractClass-独算汽车归方法7而C*rr小汽车Clftss-方法E;祖wCliass-力特*Eun.代码实现:1 namespaceCarRunOnRoad_Bridge_2 比一一34 /抽象路5 IpublicabstractclassAbstractRoad64巾7 IprotectedAbstractCarcar;8 IpublicAbstractCarCar9帆10Isetcar=value;)帕I卜上mH12

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论