软件开发设计模式.doc_第1页
软件开发设计模式.doc_第2页
软件开发设计模式.doc_第3页
软件开发设计模式.doc_第4页
软件开发设计模式.doc_第5页
免费预览已结束,剩余34页可下载查看

下载本文档

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

文档简介

软件开发设计模式yinchong目录1.概述101.1目标102.原则102.1开-闭原则102.2里氏代换原则102.3依赖倒转原则102.4接口隔离原则102.5合成/聚合原则102.6迪米特法则103.创建模式103.1简单工厂103.1.1类图103.1.2与其他模式的关系103.1.3优点和缺点113.2工厂方法模式113.2.1类图113.2.2与其他模式的关系113.2.3优点和缺点113.3抽象工厂模式123.3.1类图123.3.2使用场景123.3.3与其他模式的关系123.3.4优点和缺点123.4单例模式123.4.1类图123.4.2使用场景133.4.3与其他模式的关系133.4.4优点和缺点133.5多例模式133.5.1类图133.5.2与其他模式的关系133.5.3优点和缺点133.6建造模式143.6.1类图143.6.2使用场景143.6.3与其他模式的关系143.6.4优点和缺点153.7原始模型模式153.7.1类图153.7.2使用场景163.7.3与其他模式的关系163.7.4优点和缺点164.结构模式174.1适配器模式174.1.1类图174.1.2使用场景184.1.3与其他模式的关系184.1.4优点和缺点184.2缺省适配模式184.2.1类图184.2.2使用场景194.2.3与其他模式的关系194.2.4优点和缺点194.3合成模式194.3.1类图194.3.2使用场景214.3.3与其他模式的关系214.3.4优点和缺点224.4装饰模式224.4.1类图224.4.2使用场景224.4.3与其他模式的关系224.4.4优点和缺点224.5代理模式234.5.1类图234.5.2使用场景234.5.3与其他模式的关系244.5.4优点和缺点244.6享元模式244.6.1类图244.6.2使用场景264.6.3与其他模式的关系、264.6.4优点和缺点274.7门面模式274.7.1类图274.7.2使用场景274.7.3与其他模式的关系284.7.4优点和缺点284.8桥梁模式284.8.1类图284.8.2使用场景284.8.3与其他模式的关系284.8.4优点和缺点295.行为模式295.1不变模式295.1.1类图295.1.2使用场景295.1.3与其他模式的关系295.1.4优点和缺点305.2策略模式305.2.1类图305.2.2使用场景305.2.3与其他模式的关系315.2.4优点和缺点315.3模板方法模式315.3.1类图315.3.2使用场景325.3.3与其他模式的关系325.3.4优点和缺点325.4观察者模式325.4.1类图325.4.2使用场景345.4.3与其他模式的关系345.4.4优点和缺点345.5迭代子模式345.5.1类图345.5.2使用场景365.5.3与其他模式的关系365.5.4优点和缺点365.6责任链模式375.6.1类图375.6.2使用场景375.6.3与其他模式的关系385.6.4优点和缺点385.7命令模式385.7.1类图385.7.2使用场景395.7.3与其他模式的关系395.7.4优点和缺点395.8备忘录模式395.8.1类图395.8.2使用场景405.8.3与其他模式的关系405.8.4优点和缺点405.9状态模式415.9.1类图415.9.2使用场景415.9.3与其他模式的关系425.9.4优点和缺点425.10访问者模式425.10.1类图425.10.2使用场景425.10.3与其他模式的关系425.10.4优点和缺点435.11解释器模式435.11.1类图435.11.2使用场景445.11.3与其他模式的关系445.11.4优点和缺点445.12调停者模式445.12.1类图445.12.2使用场景455.12.3与其他模式的关系455.12.4优点和缺点451.概述1.1 目标 通过本文档能迅速想起设计模式相关知识。2. 原则2.1 开-闭原则2.2 里氏代换原则2.3 依赖倒转原则2.4 接口隔离原则2.5 合成/聚合原则2.6 迪米特法则3. 创建模式3.1 简单工厂3.1.1 类图简单工厂是类的创建模式,类图如下:3.1.2 与其他模式的关系l 单例模式单例模式使用静态工厂方法管理自己的实例。l 多例模式多例模式是单例模式的扩展,同样使用静态工厂模式管理实例。l 备忘录模式单例模式、多例模式使用备忘录模式。3.1.3 优点和缺点l 优点客户端不需要知道具体实现。只负责调用工厂方法来获取实例。l 缺点具体产品是未知数量和层次的时候,使用简单工厂模式会造成维护上的困难。3.2 工厂方法模式3.2.1 类图工厂方法模式是简单工厂模式的进一步抽象,将简单工厂中的工厂方法变为抽象工厂方法,不在进行具体类的创建,而交给抽象工厂的子类完成,类图如下:3.2.2 与其他模式的关系l 模板方法模式工厂方法模式可以和模板方法模式组合使用,通过模板方法将顶级逻辑在抽象工厂方法中进行封装。而模板方法调用几个基本方法,基本方法可以有一个或多个工厂方法,这些工厂方法代表剩余逻辑有子类实现。反之,模板方法模式可以使用工厂方法模式进行创建。l 享元模式享元模式使用带循环逻辑的工厂方法。l 备忘录模式享元模式使用备忘录模式来登记所有已经创建的产品。3.2.3 优点和缺点待补充3.3 抽象工厂模式3.3.1 类图3.3.2 使用场景l 客户端不依赖具体类(产品)的创建、组合、表达等细节。l 系统有多个产品族,而客户端只需要一个产品族。l 属于同一个产品族的产品在一起使用。l 系统提供一个产品类的库,所有产品以同样的接口实现,客户端不依赖具体实现。3.3.3 与其他模式的关系l 工厂方法模式抽象工厂方法可以通过工厂方法模式实现,每一个工厂角色都配有一个工厂方法,这个方法创建产品角色。l 原始模型模式也可以不使用工厂方法模式,而使用原始模型模式。l 桥梁模式抽象工厂方法模式可以为桥梁模式提供等级结构。可以和桥梁模式一起使用。3.3.4 优点和缺点3.4 单例模式3.4.1 类图单例模式确保类只有一个实例,并向整个系统提供这个实例,单例模式分为有状态和无状态,类图如下:3.4.2 使用场景l 系统要求一个类只能有一个实例时。3.4.3 与其他模式的关系l 多例模式单例模式的扩展,可以提供多个实例。l 简单工厂模式单例模式使用简单工厂模式提供自己的实例。3.4.4 优点和缺点3.5 多例模式3.5.1 类图多例模式允许有多个实例,多例模式必须自己创建管理自己的实例。多例模式分为有上线多例模式和无上线多例模式。类图:3.5.2 与其他模式的关系3.5.3 优点和缺点3.6 建造模式3.6.1 类图建造模式可以将产品的内部表象与产品的生成过程分割开来,从而可以使用一个建造过程生成具体有不同的内部对象的产品对象,类图:3.6.2 使用场景l 需要生成的产品对象有复杂的内部结构,每个内部成分本身可以使对象,也可以使一个对象的一个组成部分。l 需要生成的产品对象的属性互相依赖,建造模式可以强制实行一种分步骤进行的建造过程,例如否一个属性赋值后才能给其他属性赋值。l 在对象创建过程中会使用到系统中的其他一些对象,这些对象的创建过程中不易得到。3.6.3 与其他模式的关系l 抽象工厂模式1.抽象工厂模式返回的可能最终对象,也可能是客户端在得到对象后在进行建造更大更复杂的对象。抽象工厂模式更具体。2.建造者则不同,建造模式将一点一点的创建一个复杂的产品,而且这个创建过程是发生在建造者角色内部。建造模式更宏观。l 策略模式策略模式为算法提供抽象封装。l 模板方法模式省略建造模式的导演角色,可以发招到模板方法模式。l 缺省适配器模式可以使用缺省适配器模式补充建造模式,如否则具体类没有某个抽象属性时。l 合成模式合成模式描述一个对象树的组成结构,建造模式则描述对象树的生成过程。3.6.4 优点和缺点l 优点n 建造模式的使用使得产品的内部表象可以独立变化。使用建造模式可以使客户端不必知道产品内部组成的细节。n 每一个builder都相对独立,而与其他builder无关。n 模式所建造的最终产品对象更容易控制。3.7 原始模型模式3.7.1 类图通过给出一个原始类型来指明所要创建的对象的了类型,然后用复制这个原型对象的方法创建出更多同类型的对象。这就是原始模型模式的用意.简单原始模型模式,用于原始对象比较少,比较固定的。类图:登记形式的原始模型模式,用于创建原始对象不固定。类图:3.7.2 使用场景假设一个系统的产品类是动态加载的,而且产品类具有一个的登记结构。这个时候如果采取工厂模式的话,工厂类就不得不具有一个相应的等级结构。而产品类的等级结构一个变化,工厂类的结构也要跟着变化。如果使用原始模型模式,给每个产品类配备一个克隆方法(大多数情况只需给产品等级结构的跟类配备一个克隆方法),便可以避免使用工厂模式所带来的具有固定等级结构的工厂类。3.7.3 与其他模式的关系l 合成模式原始模式经常与合成模式一同使用,因为原始对象经常是合成的。l 抽象工厂模式如果系统不需要动态的改变原始对象,抽象工厂模式可以成为原始模型模式的替代品。l 门面模式原始模型模式的客户端通长可以将系统的其他对象与参与原始模型模式的对象分隔开,起到门面模式的作用。l 工厂方法模式如果原始对象只有一种,且不会增加的话,工厂方法模式可以替代原始模型模式。l 装饰模式原始模型模式经常和装饰模式一起使用。3.7.4 优点和缺点l 优点1. 原始模型允许动态增加或减少产品类。由于创建产品类实例的方法是产品类内部具有的,因此增加新产品对整个结构不会有影响。2. 原始模型提供简化的创建结构。工厂方法模式常常需要有一个与产品类等级结构相同的结构。3. 具有给一个应用软件动态加载新功能的能力。如一个分析web服务器的日志文件,针对每一种日志格式,可以创建一个格式类。如果出现新的不支持的web服务器,只需要提供一个格式类的克隆,并在客户端等级,而不需要提供新的软件包。4. 产品类不需要非得有任何事先确定的等级结构,因为原始模型模式使用于任何的等级结构。l 缺点最大的缺点是每个类都要配备一个克隆方法,克隆方法需要对功能进行通盘考虑。4. 结构模式4.1 适配器模式4.1.1 类图把一个类的接口变换成客户端所期待的另一种接口,从而使因接口不匹配而无法再一起工作的两个一起工作。类的配置器类图:对象的适配器类图:4.1.2 使用场景l 系统需要使用现有的类,而此类的接口不符合系统的需要。l 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。l 对对象适配器模式而言,在设计里,需要改变多个已有的子类的几口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这不太实际。4.1.3 与其他模式的关系l 桥梁模式桥梁模式的用意是把实现和它的接口分开,以便他们可以独立的变化。不要和适配器混淆。适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使因接口不匹配而无法再一起工作的两个一起工作。l 装饰模式装饰模式是增强现有功能。适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使因接口不匹配而无法再一起工作的两个一起工作。4.1.4 优点和缺点l 优点1. 类的适配器置换源类的方法很方便。2. 对象的配置器增加新方法很容易,且新增的方法使用于所有的源。l 缺点4.2 缺省适配模式4.2.1 类图缺省适配模式为一个接口提供一个缺省实现,这样子类可以种缺省类基础上进行扩展,而不需要对原接口进行扩展,类图:4.2.2 使用场景在任何时候,如果不准备实现接口的所有定义的方法,可以使用缺省适配模式4.2.3 与其他模式的关系4.2.4 优点和缺点4.3 合成模式4.3.1 类图合成模式将对象组织到树结构中,可以用来描述整体与部分的关系,合成模式可以使客户端将单元元素和符合元素同等看待。一个基于继承类型的等级结构便是一个数结构,一个基于合成对象的机构也是一个数结构,合成模式也是一个数据对象的树结构的模式。安全式的合成模式类图:透明式的合成模式,与安全式合成模式不同,透明式的合成模式要求所有具体构建类,不论树枝还是树叶,均符合一个固定接口。类图:4.3.2 使用场景l 需要描述对象的部分和整体的等级结构。l 需要客户端忽略掉个体构件和组合构件的区别,客户端必须平等对待所有的构件,包括个体构件和组合构件。4.3.3 与其他模式的关系l 命令模式合成模式常常应用到命令类的合成上,有几个具体命令类合成宏命令类。l 装饰模式将新的行为添加到树叶类和合成类中去,可以使用装饰模式增强。l 迭代模式合成模式常常使用迭代子模式遍历子对象。l 责任链模式一个责任链模式往往应用到一个树结构上,因此责任链模式会使用到合成模式、迭代模式和装饰模式。l 享元模式复合享元对象是合成模式的应用,抽象享元角色是复合构件角色,而具体享元角色就是具体构件角色。复合享元是树枝构件,而单纯享元是树叶构件。4.3.4 优点和缺点l 优点1. 合成模式可以很容易的增加新种类的构件。2. 使用合成模式可以使客户端变得很容易设计,因为客户端不需要知道构件是树叶还是树枝。l 缺点1. 使用合成模式后,控制树枝构件的类型就不太容易。2. 用继承的方法来增加新的行为很困难4.4 装饰模式4.4.1 类图装饰模式以对客户端透明的方式扩展对象的功能,是继承方案的一个替代方案,类图:4.4.2 使用场景l 需要扩展一个类的功能,或给一个类增加附加责任。l 需要动态地给一个对象增加功能,这些功能可以再动态地撤销l 需要增加由一些基本功能的排列组合而产品的非常大量的功能,从而使继承关系变的不现实4.4.3 与其他模式的关系4.4.4 优点和缺点l 优点1. 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以设计出很多不同行为的组合3. 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更容易出错。l 缺点使用装饰模式可以使用继承关系较少的数目类,由于类数量少,设计比较容易进行。但是装饰模式会产生比继承关系更多的对象,更多的对象使排查错误变得困难。4.5 代理模式4.5.1 类图代理模式给某一个对象提供一个代理对象,由代理对象控制原对象的引用。类图:4.5.2 使用场景代理模式的类型:l 远程代理:为一个位于不同的地址空间的对象提供一个局域代表对象。这个不同的地址空间可以使本机器中,也可以使另外一台机器中。l 虚拟代理:根据需要创建一个资源消耗较大的对象,是的此对象只在需要时才会被真正创建。l Copy-on-Write代理:虚拟代理的一种,把复制(克隆)拖延到只有在客户端需要时,才真正采取行动。l 保护代理:控制对一个对象访问,如果需要,可以根据不同的用户提供不同级别的使用权限。l Cache代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。l 防火墙代理:保护目标,不让恶意用户接近。l 同步化代理:使几个用户能够同时使用一个对象而没有冲突。l 智能引用代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象的调用次数进行记录等。虚拟代理、远程代理 、智能引用代理和保护代理最为常见。4.5.3 与其他模式的关系l 适配器模式适配器模式的用意是要改变所考虑的对象的接口,而代理模式并不能改变所代理的对象的接口,在这一点上两个模式有明显区别,不要混淆。l 装饰模式装饰模式与所装饰的对象具有相同接口,这点上和代理模式容易混淆。装饰模式应当为所装饰的对象提供增强功能;而代理模式对象是对对象使用施加控制,并不能提供对象本身的增强功能。l 门面模式门面模式有兼任代理责任的时候,这时候门面模式叫做代理门面模式或门面代理模式。4.5.4 优点和缺点l 优点1. 远程代理优点是系统可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户完全可以认为被代理是局域的而不是远程的,而代理对象承担了大部分的网络通信工作。2. 保护代理的优点是,它可以再运行时间对用户的有关权限进行检查,然后在核实后决定将调用传递给被代理的对象。3. 智能引用代理在访问一个对象时可以执行一些内务处理操作,比如计数操作等。l 缺点4.6 享元模式4.6.1 类图享元模式以共享的方式高效地支持大量的细粒度对象。享元对象能做到共享的关键是内藴状态和外藴状态。一个内蕴状态是存储在享元对象内部的,并且是不会随环境改变而有所不同的。因此,一个享元可以具有内蕴状态并可以共享。一个外蕴状态是随环境改变而改变的,不可以共享的状态。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要的使用的时候再传入到享元对象内部。外蕴状态不可以影响享元对象的内蕴状态,他们是互相独立的。单纯享元模式,所有的享元对象都是可以共享的,类图:复合享元模式,类图:4.6.2 使用场景l 一个系统有大量的对象l 这些对象消耗大量的内存l 这些对象的状态中的大部分都可以外部化l 这些对象可以按照内蕴状态分成很多的组,当把外蕴对象从对象中删除时,每一个组都可以仅使用一个对象代替l 软件系统不依赖于这些对象的身份,换言之,这些对象可以是不可分辨的。使用享元模式需要维护一个记录了系统已有的所有享元的表,而这个需求耗费资源。因此,应当在足够多的享元实例可供共享时才值得使用享元模式。4.6.3 与其他模式的关系、l 单例模式1. 享元模式中的享元对象常常和单例模式中的单例对象相混淆。2. 享元工厂(不是享元)往往是单例模式。由于只有一个系列的享元,因此系统只需要一个享元工厂实例,所以享元工厂可以设计为单例模式。l 工厂方法模式享元工厂较色是一个特俗的工厂方法模式,特殊之处在于这个工厂维护一个所创建过的产品对象的记录,并根据这个记录和产品对象的内部状态循环使用这些产品对象。l 代理模式不要将代理模式和享元模式混淆。一些初学者认为享元可以像代理对象一样,作为被代理对象的替代物使用,这是不对的。在代理模式里,为了避免加载大量的耗费资源的对象,可以使用一些轻量级的代理对象,只在系统真正使用到原始对象时才真正加载它们。享元模式不是这样。在一个使用享元模式的系统里可能看上去有很多的享元对象,好像都是独立拷贝的,但是他其实是被多个客户端共享的单一的实例。l 不变模式不变模式要求一个对象的内部状态在创建出来后就不再变化;而享元模式仅要求享元对象的内蕴状态变化不影响共享,这两者是很大的区别的。不变模式对一个对象来说是一个很强的要求,而享元模式对享元对象的约束却弱很多。l 备忘录模式享元工厂对象维护一个表,通过这个表把很多全同的实例与代表他们的一个对象联系起来,这就是备忘录模式。l 状态模式状态模式会产品大量细粒度状态对象,设计师应该认真考虑使用享元模式设计这些状态对象。l 策略模式策略模式的抽象策略角色是比较重的,而其余的具体策略角色则越轻越好。如果系统需要大量的具体策略角色的实例,那么设计师应当认真考虑使用享元模式设计这些具体策略对象。l 合成模式严格的讲,享元模式并不是一个单纯的模式,而是一个由数个模式组合而成的复合模式。享元模式的工厂角色是一个工厂方法模式,只是工厂的内部记录了所创建的产品实例,并选择使用这些实例。享元对象是合成模式的应用,抽象享元角色是复合构件角色,而具体享元角色就是具体构件角色。复合享元是树枝构件,而单纯享元是树叶构件。4.6.4 优点和缺点l 优点享元模式的优点在于它大幅度的降低内存中对象的数量。l 缺点1. 享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序逻辑复杂2. 享元模式将享元对象的状态外部话,而读取外部状态使得运行时间稍微变长。4.7 门面模式4.7.1 类图外部与一个子系统的通信必须通过一个统一的门面对象进行,这就是门面模式。类图:4.7.2 使用场景l 子系统往往应为不断演化而变得越来越复杂,使用门面模式可以使得子系统更具可复用性。Faade模式提供一个简单的默认视图,对大多数用户来说足够用,而那些需要进一步继承的用户可以越过faade层直接对子系统进行继承。l 一般而言,子系统和其他子系统之间、客户端与实现化层之间存在很大依赖性。使用faade模式将一个子系统与它的客户端以及其他子系统分离,提高子系统的独立性和可移植性。l 在构建一个层次化的系统时,可以使用faade模式定义系统中的每一层的入口。如果层与层之间是互相依赖的,则可根据限定它仅通过faade进行通信,从而简化了层与层之间的依赖关系。4.7.3 与其他模式的关系4.7.4 优点和缺点4.8 桥梁模式4.8.1 类图桥梁模式的用意是:将抽象化与实现化脱耦,使得二者可以独立地变化。类图:4.8.2 使用场景l 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的链接。l 设计要求实现化角色和任何改变不影响客户端,或者说实现化角色的改变对客户端是完全透明的。l 一个构件有多于一个的抽象化角色和实现化角色,系统需要他们之间进行动态耦合。l 虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。4.8.3 与其他模式的关系l 适配器模式对象行驶的适配器模式可能看上去很想桥梁模式,然而适配器模式的目的是要改变已有的接口,让他们可以相容,以使没有关系的两个类能一起工作。而桥梁模式是分离抽象化合实现化,使得两者的接口可以不同。因此,两个模式是相反方向努力的。l 策略模式策略模式是关于计算方法的封装,而桥梁模式是关于怎样把抽象化角色和实现化角色强耦合解除掉。两者在结构上很像,不要混淆。l 装饰模式桥梁模式和装饰模式用意很像,都要避免太多的子类。l 状态模式桥梁模式描述两个等级结构之间的关系,状态模式则描述一个对象与其(外部化)状态对象之间的关系。l 抽象工厂模式4.8.4 优点和缺点5. 行为模式5.1 不变模式5.1.1 类图一个对象的状态在对象创建后就不再变化,这是不变模式。类图:5.1.2 使用场景一个类的实例状态是不可变化的;但是这个类的子类的实例具有可能会变化的状态,这是弱不变模式,弱不变模式的满足下面条件:l 所考虑的对象没有任何方法会修改对象的状态;这样一来,当对象的构造子将对象初始化之后,对象的状态便不再变化。l 所有的属性都应当是私有的,不要声明任何公开的属性,以防止客户端对象直接修改任何的内部状态。l 这个对象所引用到的其他对象如果是可变对象的话,必须设法限制外界对这些可变对象的访问,以防止外界修改这些对象。如果可能,应当尽量在不变对象内部初始化这些被引用的对象,而不要在客户端初始化,然后再传入到不变对象内部来。如果某个可变对象必须在客户端初始化,然后在传入到不变对象里的话,就应当考虑在不变对象初始化的时候将这个改变对象复制一份,而不要使用原来的拷贝。一个类的实例的状态不会改变;同时它的子类的实例也具有不可变化的状态。这样的类符合强不变模式,要实现强不变模式,要满足所有弱不变模式的所有条件,并且还要满足下面条件之一:l 所考虑的类所有的方法都应当是final;这样这个类的子类不能够置换此类的方法。l 这类本身就是final,那么这个类就不可能会有子类,从而也就不可能又被子类修改的问题。5.1.3 与其他模式的关系l 享元模式享元模式中的享元对象可以使不变对象。实际上,大多数情况下享元对象是不变对象(但是享元模式并不要求享元对象是不变对象)。5.1.4 优点和缺点l 优点1. 不变模式可增强对象的强壮性。不变模式允许多个对象共享某一个对象,降低了对该对象进行并发访问时的同步化开销。2. 因为不能修改一个不变对象的状态,所以可以避免由此引起的不必要的程序错误,一个不变对象要比可变对象更加容易维护。3. 因为没有任何一个线程能够修改不变对象的内部状态,一个不变对象自动就是线程安全的,这样声调了同步化的开销。l 缺点一旦需要修改一个不变对象的状态,就只好创建一个新的同类对象,在需要频繁修改不变对象环境里,会有大量的对边对象作为中间结果被创建出来,在被垃圾回收掉,这是资源的浪费。5.2 策略模式5.2.1 类图策略模式是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以互相替换,策略模式可以使得算法可以在不影响到客户端的情况下发生变化。类图:5.2.2 使用场景l 注意事项1. 经常见到的是,所有的具体策略类都有一些公有的行为,这时候应当把这些公有的行为放到共同的抽象策略角色里面。当然这个时候的抽象策略角色必须要是抽象类,而不能是接口。这也是典型的将代码继承等级结构的上方集中的标准做法。2. 策略模式在每一个时刻都只能使用一个策略对象,但是有的时候一个应用程序同时与几个策略对象相联系。换言之,在应用程序启动时,所有的策略对象就已经被创立出来,而应用程序可以再几个策略对象之间调换。这只有在策略对象不会耗费很多内存资源的情况下才可行,只有策略对象的初始化会花费很长时间的情况下才需要。l 如果在一个系统里面有需要类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在需要行为中选择一种行为。l 一个系统需要动态地在几种算法中选择一种。l 一个系统的算法使用的数据不可以让客户端知道。策略模式可以避免让客户端涉及到不必要接触到的复杂的和只与算法有关的数据。l 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。使用策略模式可以避免难以维护的多重条件选择语句。5.2.3 与其他模式的关系l 建造模式策略模式和建造模式相似,区别在于它们的目的,以及什么时候使用、在什么情况下使用。l 适配器模式适配器模式在结构上和策略模式相似,区别在于它们之间的用意不同。l 享元模式如果有多个客户端对象需要调用同样的一些策略类的话,可以使它们实现享元模式。让客户端共享这些策略类。l 模板方法模式模板方法模式使用继承的方法提供不同的算法行为,策略模式使用委派的方法提供不同的算法行为。l 装饰模式策略模式和装饰模式是不同的,装饰模式的用意是在不改变接口的情况下,增强一个对象的功能;策略模式在保持接口不变的情况,是具体算法可以互换。5.2.4 优点和缺点l 优点1. 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或者行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免重复代码。2. 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或者行为。3. 使用策略模式可以避免使用多重条件孔子语句。易于维护。l 缺点1. 客户端必须知道所有的具体策略类,并需要自行决定使用哪一个策略类。这意味着客户端必须理解算法的区别。2. 策略模式造成很多的策略类。有时候可以通过把依赖于环境的状态保存到客户端里面,将策略类设计成可共享的,这样的策略类实例可以被不同客户端使用。转眼之,可以使用享元模式来减少对象的数量。5.3 模板方法模式5.3.1 类图准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法迫使子类实现剩余逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余逻辑有不同的实现,这就是模板方法。类图:5.3.2 使用场景5.3.3 与其他模式的关系5.3.4 优点和缺点5.4 观察者模式5.4.1 类图观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。第一种方式观察者模式类图:第二种方式:5.4.2 使用场景5.4.3 与其他模式的关系l 备忘录模式观察者模式使用了备忘录模式,暂时将观察者对象存储在被观察者对象里面。5.4.4 优点和缺点l 优点1. 观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者聚集,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,他只知道他们有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次,如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。2. 观察者模式支持广播通信。被观察者会像所有观察者发出通知。l 缺点1. 如果一个被观察者对象有很多直接和间接的观察者的话,将所有观察者都通知会花费很多时间。2. 如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃,一定注意。3. 如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递时以自恰的方式进行的。4. 虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应机的制使观察者知道所观察的对象是怎么发生变化的。5.5 迭代子模式5.5.1 类图迭代子可以顺序地访问一个剧集中的元素而不必暴漏聚集的内部表象。白箱集合与外禀迭代子,一个白箱集合向外界提供访问自己内部元素的接口,从而使外禀迭代子可以通过集合的遍历方法实现迭代功能类图:外禀迭代子意义:既然聚集已经向外界提供了遍历方法,客户端已经可以迭代,为什么还是使用迭代子模式?迭代子对象和迭代模式将迭代过程抽象化,将作为迭代消费者的客户端和迭代负责人的迭代子责任分隔开,使得两者独立演化。在集合类型发生变化或者迭代的方法发生改变时,迭代子作为一个中间层可以吸收变化的因素,而避免修改客户端或者集合本身。此外,如果系统需要同时针对几个不同的集合进行迭代,而这些集合对象所提供的遍历方法有所不同时,使用迭代子模式和一个外界的迭代子对象是有意义的。具有同一迭代接口的不同迭代子对象处理具有不同遍历接口的集合对象,使得系统可以使用一个统一的迭代接口进行所有的迭代。黑箱集合于内禀迭代子,一个黑箱集合不向外部提供遍历自己元素对象的接口,因此这些元素对象只可以被聚集内部成员访问。由于内禀迭代子恰好是聚集内部的成员子类,因此,内禀迭代子对象是可以访问聚集的元素的。类图:注意:内禀迭代子、外禀迭代子和外部迭代子(主动迭代)、内部迭代子(被动迭代)是不同的概念。5.5.2 使用场景5.5.3 与其他模式的关系l 合成模式迭代子模式常常用来遍历一个合成模式建立起来的结构。l 命令模式命令模式常常需要维护一个历史清单集合,并使用迭代子模式遍历历史清单的元素,命令模式需要这一功能来实现命令的撤销和恢复。l 备忘录模式迭代子对象在迭代过程中会存储迭代的状态,包括游标位置等,使用备忘录模式。l 工厂方法模式聚集角色一般提供一个工厂方法,房外提供自己的迭代子对象。5.5.4 优点和缺点l 优点1. 迭代子模式简化了集合的界面。迭代子具备了一个遍历接口,这样集合的接口就不必具备遍历接口。2. 每一个聚集对象都可以有一个或一个以上的迭代子对象,没一个迭代子的迭代状态可以使彼此独立的。因此,一个集合对象可以同时有几个迭代子在进行之中。3. 由于遍历算法被封装在迭代子角色里面,因此迭代的算法可以独立于聚集角色变化。客户端拿到的是迭代子的对象,而不知道具体集合的类型变化,不会影响客户端的遍历过程。l 缺点1. 迭代子模式给客户端一个集合被顺序化的错觉,因为大多数的情况下聚集的元素并没有确定的顺序,但是迭代必须以一定线性顺序进行。如果客户端误以为顺序是聚集本身具有的特性而过度依赖聚集元素的顺序,很可能出错。2. 迭代子给出的集合元素没有类型特征。一般而言,迭代子给出的元素都是object类型,因此,客户端必须具备这些元素类型的知识才能使用这些元素。5.6 责任链模式5.6.1 类图在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一个链,请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上哪一个请求对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态的重新组织链和分配责任。类图:5.6.2 使用场景l 系统已经有一个由处理者对象组成的链,这个链可能有合成模式给出。l 有多于一个的处理者对象会处理一个请求,而且事先并不知道是哪个一个处理者对象会处理一个请求,这个处理者对象是动态确定的。l 系统想发出一个请求,给处理者对象中的某一个,但是不明确指定哪个处理者对象处理这个请求。l 处理一个请求的处理者对象集合需要动态指定时。注意:责任链模式不负责创建责任链,责任链必须有系统的其他部分创建。5.6.3 与其他模式的关系l 合成模式当责任链模式中的链属于一个较大的结构时,这个较大的结构可能是按照合成模式构件出来的。l 命令模式责任链模式使得一个特定的请求接收对象对请求或命令的执行变得不确定,而命令模式使一个特定的对象对一个命令的执行变得明显和确定。l 模板方法模式当组成责任两的处理者对象是按照合成模式组成一个较大的结构时,模板方法模式经常用来组织单个对象的行为。5.6.4 优点和缺点5.7 命令模式5.7.1 类图命令模式把一个请求或操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和回复功能。命令模式把发出命令的责任和执行命令的责任分割开。类图:5.7.2 使用场景l 使用命令模式作为“回呼(callback)”在面向对象系统中的替代,“回呼”讲的便是先将一个函数登记上,然后在以后调用此函数。l 需要在不同的时间指定请求、将请求排队。一个命令对象和原先的请求发出者可以有不同的生命期。换言之,原先的请求发出者可能已经不在可,而命令对象本身仍然是活动的。这时命令的接受者可以是在本地,也可以在网络的另外一个地址。命令对象可以在串行化之后传送到另外一台机器上去。l 系统需要支持命令的撤销(undo)。命令对象可以把状态存储起来,等到客户端需要撤销命令所产生的效果时,可以调用undo方法,把命令所产生的效果撤销掉。命令对象还可以提供redo方法,以供客户端在需要时,再重新实施命令的效果。l 如果一个系统要将系统中所有的数据更新的日志里,以便在系统崩溃时,可以根据日志里读回所有的数据更新命令,重新调用execute方法一条一条执行这些命令,从而恢复系统在崩溃前所做的数据更新。l 一个系统需要支持交易。一个交易结构封装了一组数据更新命令。使用命令模式来实现交易结构可以使系统增加新的交易类型。5.7.3 与其他模式的关系l 合成模式合成模式可以应用到命令类的合成上,从几个具体命令类合成宏命令类。l 备忘录模式如果命令需要撤销和恢复,可以使用备忘录模式。l 原始模型模式如果命令模式带有clone方法的话,命令就可以被复制。5.7.4 优点和缺点l 优点1. 命令模式使新的命令很容易地被加入到系统里。命令模式把请求一个操作的对象和知道怎么执行一个操作的对象分隔开。2. 允许接收请求的一方决定是否要否决请求。3. 能较容易的设计一个命令队列。4. 可以容易地实现对请求的undo和redo。5. 在需要的情况下,可以较容易的将命令写入日志。l 缺点1. 使用命令模式对导致某些西头脑更有过多的具体命令类。某些系统可能需要几十个,几百个上千个具体命令类,这使得命令模式在这样的系统里变得不切实际。5.8 备忘录模式5.8.1 类图备忘录对象是一个用来存储另外一个对象内部状态的快照对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录角色对任何对象都提供一个接口(即宽接口),备忘录角色的内部所存储的状态就对所有对象公开,因此这种实现又叫做“白箱实现”,备忘录的白箱实现叫做白箱备忘录模式,类图:5.8.2 使用场景5.8.3 与其他模式的关系l 命令模式如果涉及到某个对象的可撤销操作的状态存储问题,应当考虑命令模式。l 原始模型模式如果发起人角色支持原始模型模式的话,备忘录模式可以使用原始模型模式进行备忘录的创建。l 迭代子模式当备忘录模式支持多个检查点时,在各个检查点之间进行遍历需要使用迭代子模式。5.8.4 优点和缺点l 优点1. 有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取。这时,使用备忘录可以把复杂的发起人内部信息对其他的对象屏蔽起来,从而可以恰当地保持封装的边界。2. 本模式简化了发起人类。发起人不在需要管理和保存其内部状态的一个个版本,客户端可以自行管理他们所需要的这些状态的版本。3. 当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。l 缺点1. 如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。2. 当负责人角色将一个备忘录存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提供用户一个操作是否会很昂贵。3. 当发起人角色的状态改变的时候,有可能这个状态无线。如果状态改变的成功率不高的话,不如采取“假如”协议模式。5.9 状态模式5.9.1 类图状态模式允许一个对象在其内部状态改变的时候改变其行为。这个对象看上去就像是改变了它的类一样.类图:5.9.2 使用场景l 一个对象的行为依赖于它所出的状态,对象的行为必须随着其状态的改变而改变。l 对象在某个方法里依赖一重和多重条件转移语句。这使得这些条件转移分支能够以泪的方式独立存在和烟花。维护这些独立的类也就不再影响到系统的其他部分。5.9.3 与其他模式的关系策略模式状态模式经常与策略模式相混淆。有的时候很难区分应当时候状态模式还是应当使用策略模式。5.9.4 优点和缺点5.10 访问者模式5.10.1 类图访问者的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。类图:

温馨提示

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

评论

0/150

提交评论