《设计模式-工大》PPT课件.ppt
哈尔滨工业大学计算机学院唐好选软件设计模式软件设计模式主要内容主要内容u软件设计模式基础u创建型模式u结构型模式u行为型模式广义讲,软件设计模式是可解决一类软件问题并能重复使用的软件设计方案狭义讲,设计模式是对被用来在特定场景下解决一般设计问题的类和相互通信的对象的描述。是在类和对象的层次描述的可重复使用的软件设计问题的解决方案模式体现的是程序整体的构思,所以有时候它也会出现在分析或者是概要设计阶段模式的核心思想是通过增加抽象层,把变化部分从那些不变部分里分离出来什么是设计模式什么是设计模式模式名称(Pattern Name)问题(Problem):描述应该在何时使用模式。解释了设计问题和问题存在的前因后果,可能还描述模式必须满足的先决条件解决方案(Solution):描述了设计的组成成分、相互关系及各自的职责和协作方式。模式就像一个模板,可应用于多种场合,所以解决方案并不描述一个具体的设计或实现,而是提供设计问题的抽象描述和解决问题所采用的元素组合(类和对象)效果(consequences):描述模式的应用效果及使用模式应权衡的问题模式的基本要素模式的基本要素u模式名和分类u意图:设计模式是做什么的?它的基本原理和意图是什么?它解决的是什么样的特定设计问题?u动机:说明一个设计问题以及如何用模式中的类、对象来解决该问题的特定情景u适用性:什么情况下可以使用该设计模式?该模式可用来改进哪些不良设计?如何识别这些情况?u结构:采用对象建模技术对模式中的类进行图形描述如何描述设计模式如何描述设计模式u参与者:指设计模式中的类和/或对象以及它们各自的职责u协作:模式的参与者如何协作以实现其职责u效果:模式如何支持其目标?使用模式的效果和所需做的权衡取舍?系统结构的哪些方面可以独立改变?u实现:实现模式时需了解的一些提示、技术要点及应避免的缺陷,以及是否存在某些特定于实现语言的问题u代码示例:用来说明怎样实现该模式的代码片段u相关模式:与这个模式紧密相关的模式有哪些?其不同之处是什么?这个模式应与哪些其他模式一起使用?描述设计模式(续)描述设计模式(续)u开-闭原则(OpenClosedPrincipal)u单一职责原则u里氏代换原则u依赖倒置原则u接口隔离原则设计模式的原则设计模式的原则u设计模式就是实现了上述原则,从而达到代码复用、增加可维护性的目的u定义:软件对扩展是开放的,对修改是关闭的。开发一个软件时,应可以对其进行功能扩展(开放),在进行扩展的时候,不需要对原来的程序进行修改(关闭)u好处:在软件可用性上非常灵活。可以在软件完成后对软件进行扩展,加入新的功能。这样,软件就可通过不断的增加新模块满足不断变化的新需求u由于不修改软件原来的模块,不用担心软件的稳定性开闭原则(开闭原则(OCP)u实现的主要原则u抽象原则:把系统的所有可能的行为抽象成一个底层;由于可从抽象层导出一个或多个具体类来改变系统行为,因此对于可变部分,系统设计对扩展是开放的u可变性封装原则:对系统所有可能发生变化的部分进行评估和分类,每一个可变的因素都单独进行封装开闭原则(开闭原则(OCP)u就一个类而言,应该仅有一个引起它变化的原因u每一个引起类变化的原因就是一个职责,当类具有多职责时,应把多余职责分离出去,分别创建一些类来完成每一个职责u每一个职责都是一个变化的轴线,当需求变化时会反映为类的职责的变化举例interfaceModempublicvoiddial(Stringpno);publicvoidhangup();publicsend(charc);publiccharrecv();Modem类有两个职责:连接管理和数据通信,应将它们分离单一职责原则(单一职责原则(SRP)listKov替换原则(替换原则(LSP)u定义:“继承必须确保超类所拥有的性质在子类中仍然成立”,当一个子类的实例能够替换任何其超类的实例时,它们之间才具有is-A关系u里氏替换原则是继承复用的基石,只有当派生类可以替换掉其基类,而软件功能不受影响时,基类才能真正被复用,派生类也才能够在基类的基础上增加新的行为uLSP本质:在同一个继承体系中的对象应该有共同的行为特征u例子:企鹅是鸟吗?生物学:企鹅属于鸟类LSP原则:企鹅不属于鸟类,因为企鹅不会“飞”u违反LSP的后果:有可能需要修改客户代码依赖倒置原则(依赖倒置原则(DIP)u定义:高层模块不应依赖低层模块,二者都应该依赖于抽象u高层模块只应该包含重要的业务模型和策略选择,低层模块则是不同业务和策略的实现u高层抽象不依赖高层和低层模块的具体实现,最多只依赖于低层的抽象u低层抽象和实现也只依赖于高层抽象u辅助原则u任何变量都不应该持有一个指向具体类的引用u任何类都不应该从具体类派生u任何方法都不应覆盖其任何基类中已经实现了的方法接口隔离原则(接口隔离原则(ISP)u多个和客户相关的接口要好于一个通用接口u如果一个类有几个使用者,与其让这个类载入所有使用者需要使用的所有方法,还不如为每个使用者创建一个特定接口,并让该类分别实现这些接口u在设计模式经典著作GOF95中,设计模式从应用的角度被分为三个大的类型u创建型模式/结构型模式/行为型模式u根据模式的范围分,模式用于类还是用于对象u类模式:处理类和子类之间的关系,这些关系通过继承建立,是静态的,在编译时刻便确定下来了u对象模式:处理对象间的关系,这些关系在运行时刻是可以变化的,更具动态性u从某种意义上来说,几乎所有模式都使用继承机制,所以“类模式”只指那些集中于处理类间关系的模式,而大部分模式都属于对象模式的范畴设计模式的类型设计模式的类型u用来创建对象的模式,抽象了实例化过程u工厂模式:父类负责定义创建对象的公共接口,而子类则负责生成具体对象,将类的实例化操作延迟到子类中完成u抽象工厂模式:为一个产品族提供统一的创建接口。当需要这个产品族的某一系列的时候,可以从抽象工厂中选出相应的系列创建一个具体的工厂类u单件(Singleton)模式:保证一个类有且仅有一个实例,提供一个全局访问点创建型设计模式创建型设计模式创建型设计模式创建型设计模式u生成器(Builder)模式:将复杂对象创建与表示分离,同样的创建过程可创建不同的表示。允许用户通过指定复杂对象类型和内容来创建对象,用户不需要知道对象内部的具体构建细节u原型(Prototype)模式:通过“复制”一个已经存在的实例来返回新的实例(不新建实例)。被复制的实例就是“原型”,这个原型是可定制的。原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据u结构型模式讨论的是类和对象的结构,它采用继承机制来组合接口或实现(类结构型模式),或者通过组合一些对象来实现新的功能(对象结构型模式)u组合(Composite)模式:定义一个接口,使之用于单一对象,也可以应用于多个单一对象组成的对象组u装饰(Decorator)模式:给对象动态添加额外的职责,就好像给一个物体加上装饰物,完善其功能u代理(Proxy)模式:在软件系统中,有些对象有时候由于跨越网络或者其他障碍,而不能够或者不想直接访问另一个对象,直接访问会给系统带来不必要的复杂性,这时候可以在客户程序和目标对象之间增加一层中间层,让代理对象来代替目标对象打点一切,这就是代理(Proxy)模式结构型设计模式结构型设计模式结构型设计模式结构型设计模式u享元(Flyweight)模式:Flyweight是一个共享对象,它可以同时在不同上下文(Context)使用u外观(Facade)模式:外观模式为子系统提供了一个更高层次、更简单的接口,从而降低了子系统的复杂度,使子系统更易于使用和管理。外观承担了子系统中类交互的责任u桥梁(Bridge)模式:桥梁模式的用意是将问题的抽象和实现分离开来实现,通过用聚合代替继承来解决子类爆炸性增长的问题u适配器(Adapter)模式:将一个类的接口适配成用户所期待的接口。一个适配器允许因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包装在一个已存在的类中u着力解决的是类实体之间的通讯关系,希望以面向对象的方式描述一个控制流程u模版(Template)模式:定义了一个算法步骤,并允许子类为一个或多个步骤提供实现。子类在不改变算法架构的情况下,可重新定义算法中某些步骤u观察者(Observer)模式:定义了对象之间一对多的依赖,当这个对象的状态发生改变的时候,多个对象会接受到通知,有机会做出反馈u迭代子(Iterator)模式:提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示行为型设计模式行为型设计模式u责任链(ChainofResponsibility)模式:很多对象由每一个对象对其下一个对象的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使系统可以在不影响客户端的情况下动态的重新组织链和分配责任u备忘录(Memento)模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态u命令(Command)模式:将请求及其参数封装成一个对象,作为命令发起者和接收者的中介,可以对这些请求排队或记录请求日志,以及支持可撤销操作行为型设计模式行为型设计模式u状态(State)模式:允许一个“对象”在其内部状态改变的时候改变其行为,即不同的状态,不同的行为u访问者(Visitor)模式:表示一个作用于某对象结构中的各元素的操作。可以在不改变各元素的类的前提下定义作用于这些元素的新操作u解释器(Interpreter)模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子u中介者(Mediator)模式:用一个中介对象来封装一系列的对象交互u策略(Strategy)模式:定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。策略模式使这些算法在客户端调用它们的时候能够互不影响地变化行为型设计模式行为型设计模式创建型设计模式创建型设计模式u工厂模式u抽象工厂模式u建造者模式u单件模式u原型模式创建型设计模式创建型设计模式u在面向对象编程中,常用的方法是用new操作符构造对象实例,但在有些情况下,new操作符直接生成对象会带来一些问题(1)创建对象之前必须清楚所要创建对象的类信息,但个别情况下无法达到此要求,譬如打开一个视频文件需要一个播放器对象,但是用户可能不知道具体播放器叫什么名字,需要系统分派给这个视频文件一个合适的播放器,这种情况下用new运算符并不合适工厂模式的由来工厂模式的由来(2)许多类型对象的创造需要一系列步骤u需要计算或取得对象的初始设置u需要选择生成哪个子对象实例u在生成需要对象之前必须先生成一些辅助功能对象u在这些情况,新对象的建立就是一个“过程”,而不仅仅是一个操作。为了能方便地完成这些复杂的对象创建工作,可引入工厂模式工厂模式的由来工厂模式的由来工厂模式的结构工厂模式的结构uProduct:定义工厂方法所创建对象的接口uConcreteProduct:实现Product接口uFactory:声明工厂方法,返回一个Product类型对象。Factory也可以定义一个工厂方法的缺省实现,返回一个缺省ConcreteProduct对象uConcreteFactory:重定义工厂方法,返回一个ConcreteProduct实例工厂模式的参与者工厂模式的参与者一个日志管理器:设计日志记录类,支持记录的方法有FileLogEventLog工厂模式实例分析工厂模式实例分析/LogFactory类publicabstractclassLogFactorypublicabstractLogCreate();工厂模式实例分析工厂模式实例分析/FileFactory类publicclassFileFactory:LogFactorypublicoverrideFileLogCreate()returnnewFileLog();/EventFactory类publicclassEventFactory:LogFactorypublicoverrideEventLogCreate()returnnewEventLog();publicclassApppublicstaticvoidMain(stringargs)LogFactoryfactory=newEventFactory();/FileFactoryfactory=newFileFactory();Loglog=factory.Create();log.Write();工厂模式客户端程序工厂模式客户端程序u客户程序有效避免了具体产品对象和应用程序之间的耦合,增加了具体工厂对象和应用程序之间的耦合u在类内部创建对象通常比直接创建对象更灵活u工厂模式通过面向对象的手法,将具体对象的创建工作延迟到子类,提供了一种扩展策略,较好的解决了紧耦合问题工厂模式实例分析工厂模式实例分析抽象工厂模式的由来抽象工厂模式的由来u在软件系统中,经常面临“一系列相互依赖对象”的创建工作,由于需求变化,这“一系列相互依赖的对象”也要改变,如何应对这种变化呢?如何像工厂模式一样绕过常规的”new”,提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?u一种说法:可以将这些对象一个个通过工厂模式来创建。但是,既然是一系列相互依赖的对象,它们是有联系的,每个对象都这样解决,如何保证他们的联系呢?u实例:Windows桌面主题,当更换一个桌面主题的时候,系统的开始按钮、任务栏、菜单栏、工具栏等都变了,而且是一起变的,他们的色调都很一致,类似这样的问题如何解决呢?u应用抽象工厂模式,是一种有效的解决途径抽象工厂模式的由来抽象工厂模式的由来抽象工厂模式的意图抽象工厂模式的意图u意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类u适用场合u一个系统独立于其产品创建、组合和表示时u一个系统由多个产品系列中的一个来配置时u强调一系列相关产品对象的设计以便进行联合时u提供一个产品类库,只想显示其接口而非实现时抽象工厂模式的结构抽象工厂模式的结构uAbstractFactory:声明创建抽象产品对象的操作接口uConcreteFactory:实现创建具体对象的操作uAbstractProduct:为一类产品对象声明一个接口uConcreteProduct:定义一个被具体工厂创建的产品对象抽象工厂模式的参与者抽象工厂模式的参与者实例:需要设计一个花园布局花园有三种风格:典雅型、实用型和懒人型花园中有3个位置需要种植植物:花台、墙角和花园中心抽象工厂模式的应用实例抽象工厂模式的应用实例风格/位置花台中心墙角典雅型郁金香榕树兰草实用型葡萄石榴丝瓜懒人型月季茶花竹子建造者(建造者(Builder)模式的由来)模式的由来u在软件系统中,有时面临着“一个复杂对象”的创建工作,该复杂对象通常由各个部分的子对象用一定的算法构成u这个复杂对象的各个部分经常面临着剧烈变化,但是将它们组合在一起的算法却相对稳定u如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?建造者模式的意图和适用性建造者模式的意图和适用性u意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示u适用性场合u需要生成的产品对象有复杂的内部结构u创建复杂对象的算法稳定,或建造者模式可以强迫生成一定的顺序u当构造过程允许被构造的对象有不同的表示时建造者模式的结构建造者模式的结构建造者模式的参与者建造者模式的参与者uBuilder:为创建一个Product对象的各个部件指定抽象接口uConcreteBuilder:实现Builder接口来构造和装配产品各个部件,提供一个检索产品的接口uDirector:构造一个使用Builder接口的对象uProduct:表示被构造的复杂对象u实例:设计游戏场景中的房屋u房屋由五个部分组成:地板、墙壁、窗户、门和天花板u构建房屋的步骤固定,而具体组件(门、窗等)易变u采用建造者模式分离易变组件和稳定的构建过程建造者模式的应用示例建造者模式的应用示例publicabstractclassHouse/定义一个房屋抽象类publicabstractclassBuilder/这一部分是易变的publicabstractvoidBuildFloor();/地板publicabstractvoidBuildDoor();/门publicabstractvoidBuildWindows();/窗户publicabstractvoidBuildWall();/墙壁publicabstractvoidBuildHouseCeiling()/天花板publicabstractHouseGetHouse();建造者模式的应用示例建造者模式的应用示例建造者模式的应用示例建造者模式的应用示例publicabstractclassGameManagerpublicstaticHouseCreateHouse(Builderbuilder)builder.BuildFloor();builder.BuildDoor();builder.Buildwall();builder.BuildWindows();builder.BuildHouseCeiling();returnbuilder.GetHouse();建造者模式的应用示例建造者模式的应用示例publicclassRomanHouseBuilder:BuilderpublicoverridevoidBuildDoor()publicoverridevoidBuildFloor()publicoverridevoidBuildWindows()publicoverridevoidBuildWall()publicoverridevoidBuildHouseCeiling()publicoverrideHouseGetHouse()建造者模式的应用示例建造者模式的应用示例classApppublicstaticvoidmain()Househouse=GameManager.CreateHouse(newRomanHouseBuilder();建造者模式分析建造者模式分析u建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节u每一个Builder都相对独立,而与其它Builder无关u可对构造过程更加精细控制u将构建代码和表示代码分开u建造者模式的缺点在于难于应付“分步骤构建算法”的需求变动单件(单件(SingletonSingleton)模式的由来)模式的由来u单件模式的实例较为普遍:u系统中只能有一个窗口管理器u系统中只能有一个文件系统u一个数字滤波器只能有一个A/D转换器u一个会计系统只能专用于一个公司单件模式的由来单件模式的由来u如何才能保证一个类只有一个实例并且这个实例易于被访问呢?一个全局变量使得一个对象可以被访问,但它不能防止你实例化多个对象u一个更好的办法是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法单件模式的意图和适用性单件模式的意图和适用性u意图:保证一个类仅有一个实例,并提供一个全局访问点u适用场合:u当类只能有一个实例而且用户可以从一个众所周知的访问点访问它时u当这个唯一实例是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展实例时单件模式的结构单件模式的结构uSingleton被调用的单件对象u定义一个Instance操作,允许客户访问它的唯一实例。Instance是一个类操作(一个静态成员函数)u可能负责创建它自己的唯一实例单件模式的应用示例单件模式的应用示例ClassSingleton/单件模式的定义public:staticSingleton*Instance();/通过该成员函数访问单件protected:Singleton();/构造函数为受保护型,直接实例化将出错private:staticSingleton*_instance;/指向本身唯一实例的指针;单件模式的应用示例单件模式的应用示例Singleton*Singleton:_instance=0;/初始化类成员Singleton*Singleton:Instance()If(_instance=0)_instance=newSingleton;/如果成员变量为0,则唯/一实例化return_instance;单件模式的效果分析单件模式的效果分析u对唯一实例的受控访问:因为Singleton类封装唯一实例,所以它可以严格的控制客户怎样以及何时访问它u缩小名空间:Singleton模式是对全局变量的一种改进。它避免了那些存储唯一实例的全局变量污染名空间u允许对操作和表示的精化:Singleton类可以有子类,而且用这个扩展类的实例来配置一个应用是很容易的。可以用所需要的类的实例在运行时刻配置应用原型(原型(Prototype)模式的由来)模式的由来u在软件系统中,客户希望创建一个类对象(产品)时,可能有三种情况:u知道产品具体型号(使用new运算符创建)u不知道型号,知道特定的需求(使用工厂模式)u不知道需求,但想要一个和已知对象相同的对象-使用原型模式原型(原型(Prototype)模式的意图和适用性)模式的意图和适用性u意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象u适用性:在下列情况下,应当使用Prototype模式u当一个系统应独立于其产品创建,构成和表示时u当要实例化的类在运行时刻指定时u为了避免创建一个与产品类层次平行的工厂类层次时原型模式的结构原型模式的结构u客户:客户端类向原型管理器提出创建对象请求u抽象原型:它是对各种具体原型的抽象,通常由一个接口或抽象类实现u具体原型:被复制的对象。此角色需要实现抽象的原型角色所要求的接口u原型管理器:创建具体原型类的对象,记录每一个被创建的对象原型模式的参与者原型模式的参与者u开发一个调色板,用户单击调色板上任一个方块,将会返回一个对应的颜色的实例u很自然,我们利用OO的思想,把每一种颜色作为一个对象,并为他们抽象出一个公用的父类原型模式应用示例原型模式应用示例使用原型模式开发调色板的结构图原型模式应用示例原型模式应用示例Prototype模式的优点(1)对客户隐藏具体产品类,减少了客户知道的名字的数目(2)允许客户只通过注册原型实例就可以将一个具体产品类并入系统中,客户可以在运行时刻建立和删除原型(3)具有给一个应用软件动态加载新功能的能力。由于其独立性较高,可以很容易动态加载新功能而不影响老系统(4)产品类不需要非得有任何事先确定的等级结构,适用于任何的等级结构Prototype模式的缺点:Prototype模式的最主要缺点就是每个类必须配备一个克隆方法原型模式的应用效果分析原型模式的应用效果分析u工厂模式是一种极端情况下的抽象工厂模式,而抽象工厂模式可以看成是工厂模式的一种推广u工厂模式的特点u一个抽象产品类,可以派生出多个具体产品类u一个抽象工厂类,可以派生出多个具体工厂类u每个具体工厂类只能创建一个具体的长品类实例u抽象工厂模式的特点u多个抽象产品类,每个抽象产品类可以派生出多个具体产品类u一个抽象工厂类,可以派生出多个具体工厂类u每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式与工厂模式的区别抽象工厂模式与工厂模式的区别u提供一个接口,用于创建相关和依赖对象的家族,而不需要明确指定具体类。抽象工厂允许客户使用抽象接口来创建一组相关产品,而不需要关心具体实际产出的产品是什么u总结u所有工厂都是用来封装对象的创建u简单工厂,可以把客户程序从具体类解耦u工厂方法使用继承,把对象创建委托给子类,子类实现工厂方法来创建对象u抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中u所有工厂模式都是通过减少应用程序与具体类之间的依赖关系促进松耦合u工厂方法允许类将实例化延迟到子类进行u抽象工厂创建相关的家族,而不需要依赖他们的具体类u工厂帮助我们针对抽象编程,而不是针对具体类编程抽象工厂模式与工厂模式的区别抽象工厂模式与工厂模式的区别u工厂模式:定义一个创建对象的接口,由子类决定要实例化的具体类,工厂方法让类把实例化推迟到子类u抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类u建造者模式:封装一个产品(复杂对象)的构造过程,并允许按照步骤构造,向客户隐藏了产品的内部表现u单件模式:确保一个类只有一个实例,并提供全局访问点u原型模式:当创建给定类实例的过程很昂贵或很复杂时,使用原型模式,向客户隐藏制造新实例的复杂性创建型设计模式总结创建型设计模式总结结构型设计模式结构型设计模式p适配器模式p外观模式p装饰模式p桥接模式p享元模式p代理模式p组合模式结构型模式的主要内容结构型模式的主要内容适配器模式的由来适配器模式的由来p一个team要为外界提供S类服务,但team里面没有能够完成此项任务的member,只有team外的A可以完成这项服务。为保证对外服务类别的一致性(提供S服务)p将A招安到team内,负责提供S类服务pA不准备接受招安,可安排B去完成这项任务,并让B做好A的工作,让B工作的时候向A请教,此时,B是一个复合体(提供S服务,是A的继承弟子)p将一个类的接口,转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以一起工作适配器模式使用过程适配器模式使用过程p客户通过目标接口调用适配器的方法对适配器发出请求p适配器使用被适配者接口把请求转换成被适配者的一个或者多个调用接口p客户接收到调用的结果,但并未察觉这一切是适配器在起转换作用适配器模式的意图和适用性适配器模式的意图和适用性p意图:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作p适用场合:p使用一个已经存在的类,而它的接口不符合要求p创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作p使用一些已经存在的子类,但不可能通过子类化以匹配各自接口。对象适配器可以适配它的父类接口p适配器模式分为类适配器和对象适配器类适配器类适配器p用一个具体的Adapter类对Adaptee和Target进行匹配,Adapter类多重继承Adaptee和Target类pAdapter可重定义Adaptee的部分行为,因为Adapter是Adaptee的一个子类类适配器模式示例类适配器模式示例/Target:定义Client使用的与特定领域相关的接口publicinterfaceTargetvoidrequest();/Adaptee:现在需要适配的已经存在的接口publicclassAdapteepublicvoidspecificRequest()/Adapter:对Adaptee的接口与Target接口进行适配publicclassAdapterextendsAdapteeimplementsTargetpublicvoidrequest()super.specificRequest();对象适配器对象适配器p允许一个Adapter与多个Adaptee同时工作,即Adaptee本身以及它的所有子类(如果有子类的话)同时工作。Adapter可以一次给所有的Adaptee添加功能p使用组合,不仅可以适配某个类,也可以适配该类的任何子类对象适配器模式示例对象适配器模式示例/Target:定义Client使用的与特定领域相关的接口publicinterfaceTargetvoidrequest();/Adaptee:现在需要适配的已经存在的接口publicclassAdapteepublicvoidspecificRequest()/Adapter:对Adaptee的接口与Target接口进行适配publicclassAdapterimplementsTargetpublicAdapter(Adapteeadaptee)super();this.adaptee=adaptee;publicvoidrequest()adaptee.specificRequest();privateAdapteeadaptee;适配器模式效果分析适配器模式效果分析p优点p方便设计者自由定义接口,不用担心匹配问题p缺点p属于静态结构,由于只能单继承,所以不适用于多种不同的源适配到同一个目标外观(外观(Facade)模式的由来)模式的由来毕业生教务处公安处后勤处图书馆饭卡饭卡余额借书证借书证押金身份证、学生证派遣证学生证毕业证、学位证外观(外观(Facade)模式的由来)模式的由来毕业生毕业手续代办处教务处后勤处图书馆公安处学生证 身份证 借书证 饭卡毕业证 学位证 派遣证 饭卡余额 借书证押金外观(外观(Facade)模式的由来)模式的由来外观(外观(Facade)模式的意图和适用性)模式的意图和适用性p提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用p解除客户程序与抽象类具体实现部分的依赖性,有利于移植和更改p当需要构建层次结构的子系统时,使用Faade模式定义每层的入口点。如果子系统间相互依赖,他们只需通过Faade进行通讯p外观模式的本质是让接口变得更简单外观(外观(Facade)模式的结构)模式的结构外观(外观(Facade)模式的参与者)模式的参与者pFaadep知道哪些子系统类负责处理请求p将客户的请求代理给适当的子系统对象pSubsystemClassesp实现子系统的功能p处理由Faade对象指派的任务p没有Faade的任何相关信息外观(外观(Facade)模式的效果分析)模式的效果分析p对客户端屏蔽子系统组件,减少客户端使用对象数目p实现了子系统与客户之间松耦合的关系,使得子系统组件的变化不会影响到客户p不限制客户应用子系统类装饰(装饰(Decorator)模式的由来)模式的由来p动态给对象添加额外职责。比如:一幅画有没有画框都可以挂在墙上,画是被装饰者。在挂在墙上之前,画可以被蒙上玻璃,装到框子里,玻璃画框就是装饰p不改变接口,但加入责任。Decorator提供了一种给类增加职责的方法,不是通过继承,而是通过组合实现的装饰(装饰(Decorator)模式的意图和适用性)模式的意图和适用性p意图p动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式比生成子类更为灵活p适用场合p在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责p当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立扩展,每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况是因为类定义被隐藏,或类定义不能用于生成子类装饰(装饰(Decorator)模式的结构)模式的结构pComponentp对象接口:可以给对象动态地添加职责pConcreteComponentp具体对象pDecoratorp维持一个指向Component对象的指针,并定义一个与Component接口一致的接口pConcreteDecoratorp向组件添加职责pDecorator将请求转发给它的Component对象,并有可能在转发请求前后执行一些附加的动作装饰(装饰(Decorator)模式的结构)模式的结构装饰(装饰(Decorator)模式的评价)模式的评价p使用Decorator模式可以很容易地向对象添加职责。可以用添加和分离的方法,在运行时添加和删除职责p使用Decorator模式可以很容易地重复添加一个特性,而两次继承则极容易出错p避免在层次结构高层的类有太多的特征:可以从简单的部件组合出复杂的功能。具有低依赖性和低复杂性p缺点:Decorator与Component不一样,使用装饰时不应该依赖对象标识;有许多小对象桥接(桥接(Bridge)模式的由来)模式的由来p例子:相同模块的跨平台使用p设计模块A和Bp希望模块A和B能应用在X操作系统上,让A和B继承X操作系统的接口p希望模块A和B能应用在Y操作系统上,让A和B继承Y操作系统的接口,以此类推p问题:模块A和B缺乏复用性p解决:抽象出统一的操作系统类的接口连接模块A和B的平台无关接口,通过桥接两个抽象模块来消除模块间的继承耦合,提高复用性扩展Window抽象使之用于不同种类的窗口或新的平台很不方便继承机制使得客户代码与平台相关桥接(桥接(Bridge)模式的由来)模式的由来将Window抽象和它的实现部分分别放在独立的类层次结构中针对窗口接口针对平台的窗口实现桥接(桥接(Bridge)模式的由来)模式的由来桥接(桥接(Bridge)模式的意图和适用性)模式的意图和适用性p意图:桥接模式的作用就是将抽象部分与实现部分分离,使它可以独立的变化p适用的情况p不希望在抽象和它的实现部分之间有一个固定的绑定关系p想对客户完全隐藏抽象的实现部分桥接(桥接(Bridge)模式的结构)模式的结构桥接(桥接(Bridge)模式的参与者)模式的参与者pAbstractionp定义抽象类的接口p维护一个指向Implementor类型对象的指针pRefinedAbstractionp扩充由Abstraction定义的接口pImplementorp定义实现类的接口,不一定要与Abstraction的接口完全一致,甚至可以完全不同pConcreteImplementorp实现Implementor接口并定义它的具体实现pAbstraction将Client的请求转发给它的Implementor对象桥接(桥接(Bridge)模式的效果分析)模式的效果分析p分离接口及其实现部分,抽象类的实现可以在运行时刻进行配置,一个对象甚至可以在运行时刻改变它的实现p提高可扩充性:抽象与实现两部分可以单独扩充p实现细节对客户透明,可以对客户隐藏实现细节桥接(桥接(Bridge)模式的意义)模式的意义p脱耦是指将抽象和实现之间的耦合解脱开,或者说将他们之间的强关联改成若关联p强关联是指在编译时期已经确定的,无法在运行时期动态改变的关联p弱关联是可以动态确定并可在运行时刻动态改变的关联p继承关系是强关联,聚合关系是弱关联,将两个角色之间的继承关系修改为聚合关系,就是将他们之间的强关联变换成弱关联。桥模式中的所谓脱耦就是指在一个软件系统的抽象和实现之间使用组合/聚合关系而不是继承关系,从而可以使两者可以相对独立的变化享元(享元(Flyweght)模式的由来)模式的由来p当大量使用同一种类型的实例(每个实例中包含部分相同的数据),可能极大的耗费资源,使用Flyweight模式可以提高内存效率p以CD唱片为例,每个CD有三个字段:出片日期、歌唱者姓名、唱片曲目p姓名可能重复,可能有同一个演唱者的多个不同时期不同曲目的CD。歌唱者姓名可共享,其他字段均不可共享p当你有几千张甚至更多CD时,Flyweight模式将节省更多空间,共享的flyweight越多,空间节省也就越大享元(享元(Flyweght)模式的意图和适用性)模式的意图和适用性p意图:避免大量拥有相同内容的小类的开销,使大家共享一个类(元类)p适用性p一个应用程序使用了大量的对象p冗余使用了大量的对象,造成了很大的存储开销享元(享元(Flyweght)模式的结构)模式的结构享元(享元(Flyweght)模式的参与者)模式的参与者pFlyweight:描述一个接口,可接受并作用于外部状态pConcreteFlyweight:实现Flyweight接口,并为内部状态增加存储空间。必须是可共享的,存储的状态必须是内部的pUnsharedConcreteFlyweight:不强制共享pFlyweightFactory:创建并管理