Java面向对象程序设计(第2版)第18章.ppt_第1页
Java面向对象程序设计(第2版)第18章.ppt_第2页
Java面向对象程序设计(第2版)第18章.ppt_第3页
Java面向对象程序设计(第2版)第18章.ppt_第4页
Java面向对象程序设计(第2版)第18章.ppt_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

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

文档简介

设 计 模 式,规则,面向对象语言语法规则,谋略,设计模式,设计模式含义,设计模式(Design pattern)是一套被反复使用、多数人知晓、经过分类编目的代码设计经验的总结。使用设计模式可使代码的重用性、扩展性更好,可靠性更高,更容易被他人理解。,模式四个要素,一个助记名,它用一两个词来描述模式的问题、解决方案和效果。 描述了应该在何时使用模式。它解释了设计问题和问题存在的前因后果,它可能描述了特定的设计问题,如怎样用对象表示算法等。也可能描述了导致不灵活设计的类或对象结构。有时候,问题部分会包括使用模式必须满足的一系列先决条件。 描述了设计的组成成分,它们之间的相互关系及各自的职责和协作方式。因为模式就像一个模板,可应用于多种不同场合,所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象组合)来解决这个问题。 描述了模式应用的效果及使用模式应权衡的问题。,模式名称(pattern name) 问题(problem) 解决方案(solution) 效果(consequences),模式设计的原则,开闭原则(里氏替换原则、依赖倒转原则):对修改关闭,对扩展开放。 组合/聚合复用原则:两种重要的重用手段:Inheritance & composition,能用composition就不用Inheritance。 高内聚松耦合原则(接口隔离原则、迪米特法则、单一职责原则):对象之间存在强耦合通常意味着弱内聚,而强内聚的对象通常意味着与其他对象之间存在弱耦合。面向对象设计追求强内聚、弱耦合。,模式分类表,创建型模式,Abstract Factory,1、问题:系统由不同类型的对象构成,每种类型下又可分为不同型号。系统在建立时,从每种类型中选择一种型号对象进行创建;对于多种组合创建而言,希望能用统一的方式来操作。,实现创建具体产品对象的操作,用具体工厂创建具体产品对象,使用AbstractFactory和AbstractProduct类声明的接口,2、解决方案,public void creator(AbstractFactor af) /af引用一个具体工厂实例 AbstractProductA a = af.CreateProductA(); /产生具体产品A AbstractProductB b = af.CreateProductB(); /产生具体产品B ,3、效果 优点:AbstractFactory提供了创建组合系统对象的统一接口。当系统扩展时, AbstractProductA、AbstractProductB通过继承关系可扩展出新型号的具体产品, 再由AbstractFactory扩展出新具体子类工厂进行对象的组合创建。新具体工厂 的实例对象将传递给Client端。由于Client端都是针对抽象工厂和抽象产品进 行编程的,因而Client中的代码在传入新工厂实例后不用改动,从而体现了对 扩展开放对修改关闭的开闭原则。 缺点:系统如果增加一个新类别产品AbstractProductC时,该模式难以支持; 模式没有涉及创建的一组产品如何进行装配的问题。,Client端示例代码如下:,Builder,1、问题:构成系统的对象不仅需要创建,而且需要装配,这两个方面如果没有分开,则创建代码和装配代码就紧耦合了。当希望用相同的创建过程产生不同的系统装配效果时,这种紧耦合的设计方式显然不适用。,2、解决方案:,有继承的血缘关系,因而A、B、C三个产品都有可能被新产品所 替换,而当替换发生时,Director和Client的代码不用做任何修改。 缺点:Director中创建产品A、B、C的“工艺”过程不能改变,也就是说 如果工艺过程变为创建A、B或A、B、C、D,则生成器模式不再适用。,3、效果 优点:由于创建过程和装配过程分开,因此当有新类型对象需要装配时, 新的装配方式将封装在抽象类Builder扩展出的具体子类当中,Director可以 依旧通过抽象类Builder的引用向具体Builder对象发送同样的消息。需要说明的是:对于序列图而言,完成的是A、B、C三个产品的装配,这三个产品之间没,Factory Method,1、问题:希望对不同类型的创建对象拥有共同的使用方式。,3、效果 优点:子类只关心如何实现抽象方法来创建一个具体对象,之后便自动拥有了该对象的扩展功能,即为子类提供一个挂钩以获得对象功能的扩展版本。 缺点:在Creator和Product下容易产生平行类,即每个具体的Creator子类对应产生一个Product下的具体子类对象。,2、解决方案,Prototype,1、问题:当数量稳定的对象可装配成状态多样的组合对象时,如果采用类定义的方式,则会出现类急速增长或平行类现象。,2、解决方案,缺点:如果克隆对象本身也是一个组合对象,进行克隆操作时,构件对象是克隆(深拷贝)还是共享需要进行慎重权衡。,3、效果 优点:用统一的接口克隆对象,然后装配成组合对象,避免类数量急速增长和平行类问题产生的同时,也体现了开闭原则;另外,组合对象是由克隆的对象装配而成,这意味着各组合对象之间彼此状态是相互独立的。,Singleton,1、问题:当对象占有大量的计算机资源时,希望类的对象有且只有一个;当一个对象不掌握另一对象的引用,然而希望在必要时能够向其发送消息。,3、效果 优点:保证一个类仅有一个实例;提供对某个对象的全局访问点(在程序的任意地方,通过类的静态方法得到对象引用)。 缺点:只考虑了对象创建的管理,没有考虑销毁的管理,另外也不支持对象序列化。,2、解决方案,结构型模式,Adapter模式,1、问题:已经编码完成的系统需要同其他系统进行协作,替换现有系统的部分功能,但现有系统被替换功能的使用端代码不能更换,需要协作的系统调用接口也不能更换,从而造成协作困难。 2、解决方案,(b)类适配器,(C)对象适配器,3、效果 优点:使两个异构系统能够彼此调用;对象适配器比类适配器更灵活。 缺点:类适配器对只具有单一继承特点的语言例如Java不适用。,(a)串口USB适配器,Bridge模式,1.问题:在抽象类的派生体系当中,如果既定义了具有功能使用逻辑的抽象方法,又定义了功能实现的抽象方法,这种结构会因二者组合变化让派生类数目激增。推而广之,如果一个抽象类具有二维变化特性,这将导致派生类数目的激增。 2.解决方案,3.效果 优点:将功能的使用和实现两种抽象定义分开,变继承方式为关联组合方式,从而使它们都可以独立变化,可以在程序运行时刻对它们进行选择、切换和组合,系统的结构层次也更清晰。 缺点:功能实现通过继承抽象类Windowimp来进行,这种方式灵活性不够。因为功能实现往往需要扩充,从而引起Windowimp接口的变化。.,Composite模式,1、问题:一个组合对象往往由若干构件对象组成,并且一个组合对象又有可能是另一组合对象的构件;另外,组合对象和构件对象在功能执行上没有差别。 2、解决方案,典型的composite对象结构,3、效果 优点:易于表达具有递归特点的树形层次结构的系统,并且结构中的每个对象的操作方法都一致,从而简化客户端代码的编写。 缺点:加入Composite中的所有对象出现同质化现象,即所有对象都只能从Component角度去认识,因而Component的任何改变将会扩散到整个结构当中。,Decorator,1、问题:对一个对象添加额外的装饰,但如果装饰的组合方式较多,采用类定义的方式表达装饰效果,则类的数量会激增。 2、解决方案,3、效果 优点:很容易为需要装饰的类添加装饰,看起来好像定义了新类,并且装饰方式可以自由组合;装饰对象和需要装饰的对象具有共同的操作接口。 缺点:与组成模式类似。,Facade模式,1、问题:客户端使用一个复杂子系统功能时,如果是针对子系统中的每个类的接口进行调用,则会与子系统形成复杂的耦合关系。,2、解决方案,3、效果 优点:为子系统提供一致的访问入口,这个入口使得这一子系统更加容易使用,并且屏蔽 了子系统内部的复杂逻辑,从而实现了子系统和客户端代码的弱耦合。 缺点:Facade有可能变为胖接口而与接口隔离原则相悖。,FlyWeight(享元)模式,1、问题:一个系统出现大量的细粒度对象,这些细粒度对象会造成系统内存开销的浪费和对象维护的困难。 2、解决方案,3、效果 优点:可大大降低内存中对象的数量,或者在不降低对象数量的前提下降低内 存的占用,例如案例1中,CatalogueEntry对象就可看成Part对象的享元。外部 状态可以存储也可计算,如果采用计算方式,对内存的节约效果最好,即用计算 时间来换取内存存储。 缺点:模式允许客户端直接对具体类进行编程,这与开闭原则在一定程度上相悖。,Proxy,1、问题:在一些情况下,客户端与要访问的目标对象之间建立一个代理对象,客户端通过代理来访问目标对象。代理有远程代理、虚代理、保护代理、智能指引等类型。远程代理负责同远端目标对象进行通信,客户端则直接访问本机的远程代理;虚代理在当真正创建开销很大的目标对象前,可起到临时替身的作用;保护代理用来对目标对象的访问进行权限检查;智能指引取代了简单指针,它在访问目标对象前执行一些诸如引用计数等附加操作。对于使用代理的客户端而言,如何做到对代理和目标对象的访问效果一致就是需要解决的问题。,2、解决方案 3、效果 优点:远程代理隐藏一个对象处于不同地址空间的事实;虚代理不需要创建和装载所有的对象,因此加速了应用程序的启动;保护代理和智能指引则可以有一些附加的内务操作;另外,对于开发人员而言,代理的引入简化了编程的复杂度。 缺点:代理毕竟不是目标对象,如果目标对象变化后,代理也需要更新。如果代理数量多且部署分散,则更新困难。,行为型模式,Chain of Responsibility(职责链),1、问题:一个消息请求可能被多个接收对象处理,同时一个接收者也可以对应多个消息发送者。如何使消息的发送者和接收者的耦合关系变得灵活,即请求的发送者不需要指定具体的接收者,让请求的接收者自身在运行时决定是否处理请求,就是应该解决的主要问题。,2、解决方案,解决方案:,3、效果 优点:解除了发送者和接收者的直接耦合; 可以动态地对链进行增加和修改以改变处 理一个请求的职责。 缺点:请求在链中不能保证一定被处理。,Command模式,1、问题:在软件系统中,命令的调用者与接收者通常直接耦合。但在某些情况下,如对命令需要进行记录、撤销等处理,这种直接耦合将无法满足要求。 2、解决方案,3、效果。 优点:将命令发送者和接收者解耦,记录它们之间的行为交互;有新的命令对象时,扩展抽象类Command具体子类,且Invoker不用进行任何改动就可和新的Receiver对象进行耦合;如果和Composite模式结合,则可装配成为一个复合命令,可以与更多的接收者进行动态耦合。 缺点:可能会产生数量较大的命令类。,Interpreter模式,1、问题:经常发生的一类问题易于理解和定义,则可用语言来表示,因而需要建立语法解释器来解释语言中的句子 。,2、解决方案,3、效果 在易于实现语法解释的同时,也易于通过类的继承来扩展语法。 缺点:表达复杂的语法会使类数量变得庞大。,Iterator模式,1.问题:不同类型集合对象的内部结构不尽相同,对它们进行遍历会因结构的不同而导致算法不同,这样就对客户端遍历操作带来不便。 2.解决方案,3.效果 优点:在不暴露Aggregate内部结构的情况下,用统一的Iterator对其结构不同的各种子类进行遍历;另外Aggregate可分别创建多种Iterator子类实例,这样就可对一种集合对象采用多种方法进行遍历。 缺点:迭代得到的对象引用将失去类型特征,必须进行相应的类型转化;遍历顺序常给人以集合对象内部存储结构顺序的错觉。,Mediator模式,1、问题:随着系统中对象数量的增多,系统对象之间的耦合关系也会越来越复杂,如何降低系统对象间的耦合度就是需要解决的问题 。,2、解决方案,3、效果 优点:中间者模式将Colleague之间的强耦合变为弱耦合,这样就可独立地改变和复用各自的Colleague类和Mediator类。Colleague与Mediator之间是抽象耦合,Colleague不知道其所通信的Mediator究竟是哪个具体类,因而无论哪个继承层次的Colleague对象都可向Mediator对象发送消息,进而Colleague任意继承层次的类对象之间都可以进行相互通信;Mediator将原本分布于多个对象间的行为集中起来,改变这些行为只需要产生Mediator的子类即可。 缺点:中介者模式将交互的复杂性变为中介者的复杂性,这有可能使得中介者自身成为一个难以维护的庞然大物。,Memento模式,1、问题:称为原发器的对象常需要将内部的状态保存到外部的管理对象当中,形成具有历史记录的备忘录,必要时(例如执行Undo命令)可恢复原发器的状态,这个过程必须解决备忘录信息对管理者屏蔽而对原发器开放的问题。,3、效果 优点:使用备忘录可以避免暴露一些只应由原发器管理却又必须存储在原发器之外的信息。 缺点:如果原发器内部状态过多,拷贝到备忘录中的信息可能过大,导致代价过高;另外维护备忘录也有开销过大的潜在问题。,2、解决方案,Observer模式,问题:数据与表现形式是两个不同的概念,它们的关系可以用目标和观察者来说明。一个目标可以对应多个观察者,将目标和观察者分开有利于系统的设计,因为多个观察者可以共享一个目标。目标变化了,观察者也应变化,这样,目标如何保持与众多观察者数据状态的同步以及众多观察者之间的数据状态如何同步就是应该着重解决的问题。,图中,subject代表数据对象,它有三个observers对象,分别用表格、柱状图、饼图来展现subject中的数据。改变表格中的数据时,也就是改变了subject中的数据,之后柱状图和饼图对象收到通知,到subject中取回最新数据并进行界面刷新。如果站在observers的角度看,就实现了它们之间的数据状态同步。subject与observers这种交互关系也称为发布订阅,目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。,2、解决方案,3、效果 优点:Subject和Observer各自可以独立变化,因而当观察者类型增加或要求变 更时,Subject可以不受影响,反之亦然;另外当目标状态变化时,目标就以广 播通信的方式通知各观察者,各观察者的数据状态因此可以保持同步,另外对 消息是否进行处理取决于各观察者自身。 缺点:一个观察者可能不知道另一个观察者的存在,它对目标的错误改变有可能 殃及其他的观察者,造成其他观察者错误的更新。,State模式,1、问题:对象的状态决定对象的行为,对象状态变化后,其行为也相应变化,通常采用条件语句来实现。例如当对象扩展出一个新状态后,增加一条case语句,case下放置行为代码,这样的设计违背了开闭原则。,2、解决方案,3、效果 优点:状态对象化后,如果Context出现新的状态,可对State扩展出具体子类,而Context中的代码不用修改,体现了开闭原则。 缺点:如果Context的状态过多,则会造成State具体类过多。,class Context void request(State s) s.handle(); ,class Context void request() switch(a) case 1: System.out.println(1); break; case 2: System.out.println(2); break; ,a的取值可能因为需要不断变化,所以case语句也需要不断增加,从而Context类不断更改。,abstract class State abstract void handle(); ,class State1 extends State void handle()System.out.prinln(1); ,class State2 extends State void handle()System.out.prinln(2); ,:state2,:state1,:staten,当状态增加时,只需产生具体的state的子类,Context的request中的代码不用调整,Context代码稳定的同时,其内部状态可以不断扩展,并且行 为也发生改变,这是在没有修改类Context的条件下完成的。 Context的稳定保证了发布出去的软件版本的稳定,扩展的具 体子类则包含在新的版本中。,Class Context State current; void setState(State s) current=s; void request() if(current!=null) current.handle(); current.goNext(this); ,当Context的状态具有不断切换的要求下,可设计为:,abstract class State abstract void handle(); abstract void goNext(Context ct); ,class State1 extends State void handle()System.out.prinln(1); void goNext(Context ct) ct.setState(new state2(); ,Context中保留

温馨提示

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

评论

0/150

提交评论