《第5章 面向对象的设计原则与模式1.ppt》由会员分享,可在线阅读,更多相关《第5章 面向对象的设计原则与模式1.ppt(33页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第第5 5章章面向对象的设计模式及应用目标n掌握设计模式的基本概念n掌握几个基本的设计模式n学会运用常见的设计模式n理解面向对象的设计原则内容大纲n从一个例子开始影片出租店的程序n什么是设计模式n几个基本的设计模式单例模式、工厂模式、原型模式、组合模式、适配器模式、桥接模式、装饰模式、责任链模式n面向对象的设计原则从一个例子开始影片出租店的程序n这是一个影片出租店的程序,计算每一位顾客的消费金额并打印报表。操作者告诉程序:顾客租了哪些影片、租期多长,程序便根据租赁时间和影片类型算出费用。影片分为三类:普通片、儿童片和新片。除了计算费用还要为常客计算点数;点数会随着“租片种类是否为新片”而有所不
2、同。影片出租店的程序n初始代码n这个起始程序给你留下什么印象?我会说他设计的不好,而且很明显不符合面向对象的精神。对于这样的一个小程序,这点缺点其实没有什么关系。快速而随性(quick and dirty)地设计一个简单的程序并没有错。但如果这是复杂系统中具有代表性的一段,那么我就真的要对这个程序信息动摇了。Customer里头那个长长的statement()做的事情实在太多了,他做了很多原本应该由其他class完成的事情。影片出租店的程序n即便如此,这个程序还能继续工作。所以这只是美学意义上的判断,只是对丑陋代码的厌恶,是吗?在我们修改这个系统之前的确如此。编译器才不会在乎代码好不好看呢。但
3、是当我们打算修改系统的时候,就涉及到了人,而人在乎这些。差劲的系统是很难修改的,因为很难找到修改点。如果很难找到修改点,程序员就很有可能犯错,从而引入臭虫(bugs)。影片出租店的程序n在这个例子里,我们的用户希望对系统做一点修改。首先他们希望以HTML格式打印报表,这样就可以直接在网页上显示,这非常符合潮流。现在请你想一想,这个变化会带来什么影响。看看代码你就会发现,根本不可能在打印HTML报表的函数中复用(reuse)目前statement()的任何行 为。你 唯 一 可 以 做 的 就 是 编 写 一 个 全 新 的htmlstatement(),大量重复statement()行为。当然
4、,现在做这个还不太费力,你可以把statement()复制一份然后按需要修改就是。影片出租店的程序n但如果计费标准发生变化,又会发生什么事?你必须同时修改statement()和htmlstatement(),并确保两处修改的一致性。当你后续还有再修改时,剪贴(copy-paste)问题就浮现出来了。如果你编写的是一个永不需要修改的程序,那么剪剪贴贴就还好,但如果程序要保存很长时间,而且可能需要修改,剪贴行为就会造成潜在的威胁。影片出租店的程序n现在,第二个变化来了:用户希望改变影片分类规则,但是还没有决定怎么改。他们设想了几种方案,这些方案都会影响顾客消费和常客积点的计算方式。作为一个经验丰
5、富的开发者,你可以肯定:不论用户提出什么方案,你唯一能够获得的保证就是他们一定会在若干个月之内再次修改它。影片出租店的程序n为了应付分类规则和计费规则的变化,程序必须对statement()作出修改。但如果我们把statement()内的代码拷贝到用以打印HTML报表的函数中,我们就必须确保将来的任何修改在两个地方保持一致。随着各种规则变得愈来愈复杂,适当的修改点愈来愈难找,不犯错的机会也愈来愈少。影片出租店的程序n你的态度也许倾向尽量少修改程序:不管怎么说,它还运行得很好。你心里头牢牢记着那句古老的工程学格言如果它没坏,就别动它。这个程序也许还没坏掉,但它带来了伤害。它让你的生活比较难过,因
6、为你发现很难完成客户所需的修改。这时候就该重构技术粉墨登场了。影片出租店的程序n从Customer类中statement方法中分离出amountFor功能namountFor方法中变量名称的修改任何一个傻瓜都能写出计算机可以理解的代码。唯有写出人类容易理解的代码,才是优秀的程序员n搬移amountFor方法,变更函数名称n去掉临时变量thisAmountn对frequentRenterPoints进行类似于amountFor方法的处理n去掉临时变量totalAmount和frequentRenterPointsnMovie的继承与多态影片出租店的程序n我们从中体会到了什么?我们为什么不能一开始
7、就能设计出最后的程序?因为我们没有抓住面向对象设计中的一种规律设计模式就是前人为我们总结出的面向对象设计的一种规律,我们所要做的就是吸收消化,并加以运用设计模式出场啦设计模式基础什么是设计模式n模式(pattetn)就是做事的一种方法,也即实现某个目标的途径,或者技术。这种捕获有效技术的思想可以应用到许多领域当中,比如烹饪、焰火制品生产、软件开发以及其他一些行业。对于任何一个正迈向成熟的行业,人们总会开始寻找一些通用和有效的方法,来达到目标并解决不同场合中的问题。由某个行业的从业人员组成的社区通常会发明一些专业术语,以便于同行之间进行交流。其中某些专业术语被成为模式,即实现特定目标的公认技术。
8、随着某个行业及其专业术语的发展,一些作者便开始起到重要的作用。他们将某个行业的模式记录归档,参与标准化专业术语,并且公开传播这些有效的技术。设计模式基础什么是设计模式n在面向对象的软件设计中,总是希望避免重复设计或尽可能少做重复设计。有经验的面向对象设计者的确能做出良好的设计,而新手则面对众多选择无从下手,总是求助于以前使用过的非面向对象技术。有经验的设计者显然知道一些新手所不知道的东西,这又是什么呢?n内行的设计者知道:不是解决任何问题都要从头做起。他们更愿意复用以前使用过的解决方案。当找到一个好的解决方案,他们会一遍又一遍地使用。这些经验是他们成为内行的部分原因。它们帮助设计者将新的设计建
9、立在以往工作的基础上,复用以往成功的设计方案。一个熟悉这些模式的设计者不需要再去发现它们,而能够立即将它们应用于设计问题中。设计模式基础什么是设计模式n设计模式使人们可以更加简单方便地复用成功的设计和体系结构,帮助你做出有利于系统复用的选择,避免设计损害了系统复用性。通过提供一个显式类和对象作用关系以及它们之间潜在联系的说明规范,设计模式甚至能够提高已有系统的文档管理和系统维护的有效性。简而言之,设计模式可以帮助设计者更快更好地完成系统设计。设计模式基础什么是设计模式nChristopher Alexander是最早将某个行业的最佳实践记录为模式的作者之一。他研究的领域是建筑(而不是软件)的架
10、构。其著作A Pattern Language:Towns,ConstructionAlexander、Ishikouwa 和Silverstein,1977介绍了成功设计房屋和城镇的模式。该著作影响深远,甚至影响到软件开发行业。该书之所以能够影响其他行业,部分原因是因为它给出了一种独特的观察目标的方式。nChristopher Alexander 说过:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”。尽管Alexander所指的是城市和建筑模式,但他的思想也同样适用于面向对象设计模式,只是在面向对象的解决方
11、案里,我们用对象和接口代替了墙壁和门窗。两类模式的核心都在于提供了相关问题的解决方案。几个基本的设计模式单例模式n1:环境:环境:几乎在每个应用程序中,都需要有一个从中进行全局访问和维护某种类型数据的区域。在面向对象的(OO)系统中也有这种情况,在此类系统中,在任何给定时间只应运行一个类或某个类的一组预定义数量的实例。例如,当使用某个类来维护增量计数器时,此简单的计数器类需要跟踪在多个应用程序领域中使用的整数值。此类需要能够增加该计数器并返回当前的值。又如建立目录、数据库连接、Windows针对所有用户都应有一个回收站等,都需要这样的单对象的操作。对于这种情况,所需的类行为应该仅使用一个类实例
12、来维护该整数,而不是使用多个类实例来维护该整数。最初,人们可能会试图将计数器类实例只作为静态全局变量来创建。这是一种通用的方法,但实际上只解决一部分问题;它解决了全局可访问性问题,但没有采取任何措施来确保在任何给定的时间只运行一个类实例。应该由类本身来负责只使用一个类实例,而不是由类用户来负责。应该始终不要让类用户来监视和控制运行的类实例的数量。几个基本的设计模式单例模式n2:问题:问题采用什么方法来控制创建类实例的个数,然后确保在任何给定的时间只创建一个类实例。这会确切地给我们提供所需的行为,并使客户端不必了解任何类细节。n3 3:解决方案:解决方案私有的静态属性,类的唯一实例将构造函数私有
13、化通过共有的函数返回Instance几个基本的设计模式单例模式n一般一般SingletonSingleton模式通常有如下两种种形式,第一种叫饿汉式,模式通常有如下两种种形式,第一种叫饿汉式,第二种叫懒汉式。饿汉式在类一实例化的时候就初始化了第二种叫懒汉式。饿汉式在类一实例化的时候就初始化了instanceinstance;懒汉式仅在调用时才初始化。;懒汉式仅在调用时才初始化。npublicclassSingletonprivateSingleton()privatestaticSingletoninstance=newSingleton();publicstaticSingletongetI
14、nstance()returninstance;npublicclassSingletonprivatestaticSingletoninstance=null;publicstaticsynchronizedSingletongetInstance()if(instance=null)instancenewSingleton();returninstance;几个基本的设计模式单例模式n注意到注意到lazy initializationlazy initialization形式中的形式中的synchronizedsynchronized,这个,这个synchronizedsynchroniz
15、ed很重要,如果没有很重要,如果没有synchronizedsynchronized,那么使用,那么使用getInstancegetInstance()()是有可能得到多个是有可能得到多个SingletonSingleton实例。实例。几个基本的设计模式工厂模式n为什么要有工厂模式?为什么要有工厂模式?n就拿我们一开始学到的手机发短信的例子,如果没有就拿我们一开始学到的手机发短信的例子,如果没有“手机工手机工厂厂”,就等于将手机对象的创建工作放到所有的客户,就等于将手机对象的创建工作放到所有的客户(ClientClient)中完成,没有实现良好的封装和重用,也违背了)中完成,没有实现良好的封装
16、和重用,也违背了OCPOCP原则与原则与DIPDIP原则。原则。DIPDIP原则告诉我们:要对接口编程,不要对实原则告诉我们:要对接口编程,不要对实现编程,只有这样才能更好地实现现编程,只有这样才能更好地实现OCPOCP。在手机工厂的例子中,。在手机工厂的例子中,工厂就是创建具体手机的接口。工厂就是创建具体手机的接口。n今天我去市场,要决定是买水果等产品,还是选择种水果的产今天我去市场,要决定是买水果等产品,还是选择种水果的产品。具体怎么操作自己选择。来到市场,我发现主要有一些水品。具体怎么操作自己选择。来到市场,我发现主要有一些水果:苹果(果:苹果(AppleApple),葡萄(),葡萄(G
17、rapeGrape)和鸭梨()和鸭梨(PearPear)。到底买)。到底买什么好呢?我决定买苹果。什么好呢?我决定买苹果。几个基本的设计模式工厂模式n三种工厂模式三种工厂模式nSimple FactorySimple Factory模式模式n专门定义一个类来负责创建其它类的实例,被创建的实例通常专门定义一个类来负责创建其它类的实例,被创建的实例通常都具有共同的父类。都具有共同的父类。nFactory MethodFactory Method模式模式n将对象的创建交由父类中定义的一个标准方法来完成,而不是将对象的创建交由父类中定义的一个标准方法来完成,而不是其构造函数,究竟应该创建何种对象由具体
18、的子类负责决定。其构造函数,究竟应该创建何种对象由具体的子类负责决定。nAbstract FactoryAbstract Factory模式模式 n提供一个共同的接口来创建相互关联的多个对象。提供一个共同的接口来创建相互关联的多个对象。几个基本的设计模式工厂模式nSimple FactorySimple Factory模式模式几个基本的设计模式工厂模式nSimple FactorySimple Factory模式模式n我要购买苹果,只需向工厂角色(我要购买苹果,只需向工厂角色(BuyFruit)请求即可。而工)请求即可。而工厂角色在接到请求后,会自行判断创建和提供哪一个产品。厂角色在接到请求后
19、,会自行判断创建和提供哪一个产品。n但是对于工厂角色(但是对于工厂角色(BuyFruit)来说,增加新的产品(比如说)来说,增加新的产品(比如说增加草莓)就是一个痛苦的过程。工厂角色必须知道每一种产增加草莓)就是一个痛苦的过程。工厂角色必须知道每一种产品,如何创建它们,以及何时向客户端提供它们。换言之,接品,如何创建它们,以及何时向客户端提供它们。换言之,接纳新的产品意味着修改这个工厂。纳新的产品意味着修改这个工厂。n因此因此SimpleFactory模式的开放性比较差。模式的开放性比较差。n有什么办法可以解决这个问题吗?那就需要有什么办法可以解决这个问题吗?那就需要FactoryMethod
20、模模式来为我们服务了。式来为我们服务了。几个基本的设计模式工厂模式nFactory MethodFactory Method模式模式几个基本的设计模式工厂模式nFactory MethodFactory Method模式模式 n工厂方法模式和简单工厂模式在结构上的不同是很明显的。工厂方法工厂方法模式和简单工厂模式在结构上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。工厂方法模式可以允许很多具体工厂类从抽象工厂类中将创建类上。工厂方法模式可以允许很多具体工厂类从抽象工厂类中将创建行为继承下来
21、,从而可以成为多个简单工厂模式的综合,进而推广了行为继承下来,从而可以成为多个简单工厂模式的综合,进而推广了简单工厂模式。简单工厂模式。n工厂方法模式退化后可以变得很像简单工厂模式。设想如果非常确定工厂方法模式退化后可以变得很像简单工厂模式。设想如果非常确定一个系统只需要一个具体工厂类,那么就不妨把抽象工厂类合并到具一个系统只需要一个具体工厂类,那么就不妨把抽象工厂类合并到具体的工厂类中去。由于反正只有一个具体工厂类,所以不妨将工厂方体的工厂类中去。由于反正只有一个具体工厂类,所以不妨将工厂方法改成为静态方法,这时候就得到了简单工厂模式。法改成为静态方法,这时候就得到了简单工厂模式。n如果需要
22、加入一个新的水果,那么只需要加入一个新的水果类以及它如果需要加入一个新的水果,那么只需要加入一个新的水果类以及它所对应的工厂类。没有必要修改客户端,也没有必要修改抽象工厂角所对应的工厂类。没有必要修改客户端,也没有必要修改抽象工厂角色或者其他已有的具体工厂角色。对于增加新的水果类而言,这个系色或者其他已有的具体工厂角色。对于增加新的水果类而言,这个系统完全支持统完全支持“开开-闭闭”原则。原则。n对对FactoryMethod模式而言,它只是针对一种类别(如本例中的水模式而言,它只是针对一种类别(如本例中的水果类果类Fruit),但如果我们还想买肉,那就不行了,这是就必须要),但如果我们还想买
23、肉,那就不行了,这是就必须要AbstractFactoryMethod模式帮忙了。模式帮忙了。几个基本的设计模式工厂模式nAbstract Factory MethodAbstract Factory Method模式模式 Apple与CowMeat是一个产品的两个套件几个基本的设计模式工厂模式nFactory MethodFactory Method模式模式 n抽象工厂模式可以向客户端提供一个接口,使得客户端在不必抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,创建多个产品族中的产品对象。指定产品的具体类型的情况下,创建多个产品族中的产品对象。这就是抽象工厂
24、模式的用意。这就是抽象工厂模式的用意。n抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。的一种形态。工厂模式的更具体的工厂模式的更具体的阐述见阐述见JavaJava与模式与模式一书的一书的12121414章章几个基本的设计模式原型模式nPrototypePrototype模式模式 n打开文件打开文件几个基本的设计模式组合模式nComposite模式模式nJava与模式与模式P411上图上图n合成模式的一种简化模式合成模式的一种简化模式去除叶类去除叶类当合成模式的三个角色合并时,合成模式可以采用如左图所示的结构。可以通过子节点的值是否为null来判断它是不是叶节点。这种方法的一个很大优势在于,可通过在运行时为叶节点增加子节点而使它成为非叶节点;而缺陷在于不存在抽象层(不管是否应用设计模式,将抽象层提炼出来通常是一个很好的实践,因为能够使用抽象层的更加通用的类来编写客户的代码)。当客户端应用不关心节点是否为叶节点还是枝节点时(即客户端想对叶节点和枝节点一视同仁时),可以采用该种模式。几个基本的设计模式n适配器模式:Java与模式P359n责任链模式:Java与模式P785面向对象的设计原则n开闭原则n里氏替换原则n依赖倒转原则n接口隔离原则n合成聚合复用原则(使用聚合替代继承)n迪米特法则