敏捷软件开发第五讲开闭原则与里氏替换原则ppt课件_第1页
敏捷软件开发第五讲开闭原则与里氏替换原则ppt课件_第2页
敏捷软件开发第五讲开闭原则与里氏替换原则ppt课件_第3页
敏捷软件开发第五讲开闭原则与里氏替换原则ppt课件_第4页
敏捷软件开发第五讲开闭原则与里氏替换原则ppt课件_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

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

文档简介

1、广州大学华软软件学院软件工程系主讲教师:谭翔纬答疑时间:周三 10:30-12:00 周四 9:00-12:00Tel:660028Email:第五讲:开闭原则与里氏替换原则目录目录n开放开放封闭原则封闭原则OCP)nOCP编程实例编程实例nOCP原则实施要点原则实施要点nLiskov替换原则替换原则nLiskov原则实施要点原则实施要点n总结总结开放封闭原则OCP) 什么是软件开发过程中最不稳定的因素? 答案是需求!需求在软件开发过程中时时刻刻都可能发生变化。那么,如何灵活应对变化是软件结构设计中最重要也是最困难的一个问题。好的设计带来了极大了灵活性,不好的设计则充斥着僵化的臭味。所以我们要

2、遵循开放封闭原则OCP。开放封闭原则OCP) Bertrand Meyer,面向对象技术大师,发明了Eiffel 语言和按契约设计Design by Contract的思想,名著的作者,法国工程院院士。目前,他除了担任Eiffel环境和工具开发公司ISE的CTO之外,还是爱因斯坦的母校苏黎世联邦工学院计算机科学系教授,担任软件工程项目主席,同时还在澳大利亚Monash大学任教。他于1988年提出了著名的开放封闭原则OCP)。开放封闭原则的现实意义开放封闭原则OCP,Open Closed Principle是所有面向对象原则的核心。软件设计本身所追求的目标就是封装变化、降低耦合。而开放封闭原则

3、正是对这一目标的最直接体现。其他的设计原则,很多时候是为实现这一目标服务的,例如后面将介绍的Liskov替换原则实现最佳的、正确的继承层次,就能保证不会违反开放封闭原则。OCP核心的思想是:软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。OCP特征 软件实体类、模块、函数等应该是可扩展的,但是不可修改的。OCP有两大特征:对于扩展是开放的Open for extension) 模块的行为可以扩展,当应用的需求改变时,可以对模块进行扩展,以满足新的需求。对于更改是封闭的Closed for modification) 对模块行为扩展时,不必改动模块的源代码或二进制

4、代码。OCP的关键在于抽象lOCP的关键在于抽象l抽象技术:abstract class, Interfacel抽象预见了可能的所有扩展闭)l由抽象可以随时导出新的类开)ClientServerServerClient InterfaceClient范例:手与门l如何在程序中模拟用手去开门和关门?l行为:l开门open)l关门close)l判断门的状态isOpened)设计实现新的需求解决新的需求:修改设计符合OCP的设计方案新的实现新的需求OCP原则实施要点l预测变化和预测变化和“贴切的构造贴切的构造l 上述的例子其实并不是完全封闭的,如果手上述的例子其实并不是完全封闭的,如果手增加了新的动

5、作,例如搬运,很多地方还是会有增加了新的动作,例如搬运,很多地方还是会有改动变化。那么原来所选定的抽象对于这种变化改动变化。那么原来所选定的抽象对于这种变化来说反到成为一种障碍。来说反到成为一种障碍。l 一般而言,无论模块是多么的一般而言,无论模块是多么的“封锁封锁”,都会存在一些无法对之封闭的变化。没有对于所都会存在一些无法对之封闭的变化。没有对于所有的情况都贴切的模型。有的情况都贴切的模型。l 设计人员必须对于他们设计的模块应该对设计人员必须对于他们设计的模块应该对哪种变化封闭做出选择。哪种变化封闭做出选择。 必须先猜测出最有可能必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离变化。

6、发生的变化种类,然后构造抽象来隔离变化。OCP原则实施要点l要避免进行多余的抽象要避免进行多余的抽象l 遵循遵循OCPOCP的代价也是昂贵的。创建正确的抽的代价也是昂贵的。创建正确的抽象是要花费时间和精力的。同时这些抽象也增加象是要花费时间和精力的。同时这些抽象也增加了软件的复杂性。因此,开闭原则很难被完全实了软件的复杂性。因此,开闭原则很难被完全实现,只能在某些模块、某种程度上、某个限度内现,只能在某些模块、某种程度上、某个限度内符合符合OCPOCP的要求。所以可以说,的要求。所以可以说,OCPOCP具有理想主义具有理想主义的色彩,是的色彩,是OODOOD的终极目标。的终极目标。l 在项目很

7、紧张的情况下,一般只会对能百在项目很紧张的情况下,一般只会对能百分之百预测到的变化经行抽象,而且要是那种会分之百预测到的变化经行抽象,而且要是那种会经常发生变化的部分才进行抽象。经常发生变化的部分才进行抽象。OCP原则实施要点l隔离变化的手段隔离变化的手段l1. 1. “只受一次愚弄只受一次愚弄”l 这意味着在我们最初编写代码时,假设变化这意味着在我们最初编写代码时,假设变化不会发生;当变化发生时,我们就创建抽象来隔不会发生;当变化发生时,我们就创建抽象来隔离以后发生的同类变化。离以后发生的同类变化。l2. 2. 刺激变化。刺激变化。l我们首先编写测试我们首先编写测试l我们使用很短的迭代周期进

8、行开发我们使用很短的迭代周期进行开发一个周期一个周期为几天而不是几周为几天而不是几周l我们在加入基础结构之前就开发特性,并且经常我们在加入基础结构之前就开发特性,并且经常性的把那些特性展示给涉众性的把那些特性展示给涉众l我们首先开发最重要的特性我们首先开发最重要的特性l尽早的、经常的发布软件尽早的、经常的发布软件Liskov替换原则LSP)lLSPLSPThe Liskov Substitution Principle, LiskovThe Liskov Substitution Principle, Liskov替换替换原则)原则) l“若对于类型若对于类型S S的任一对象的任一对象o1o1

9、,均有类型,均有类型T T的对象的对象o2o2存在,存在,使得在使得在T T定义的所有程序定义的所有程序P P中,用中,用o1o1替换替换o2o2之后,程序的行之后,程序的行为不变,则为不变,则S S是是T T的子类型的子类型”p如果在任何情况下,子类或子类型如果在任何情况下,子类或子类型或实现类与基类都是可以互换的,或实现类与基类都是可以互换的,那么继承的使用就是合适的。为了达那么继承的使用就是合适的。为了达到这一目标,子类不能添加任何父类到这一目标,子类不能添加任何父类没有的附加约束没有的附加约束p“子类对象必须可以替换父类对象子类对象必须可以替换父类对象”从问题开始!l长方形与正方形长方

10、形与正方形l假如我们有一个类:长方形假如我们有一个类:长方形RectangleRectangle)l我们需要一个新的类,正方形我们需要一个新的类,正方形SquareSquare)l问:可否直接继承长方形?问:可否直接继承长方形?开始设计:正方形设计方案正确吗?违背LSP原则-23-怎么办?ABABC-24-解决方案IS-A关系的思考?l鸵鸟是鸟吗?是l鸵鸟有翅膀,鸟也有翅膀l鸵鸟有喙,鸟也有喙l但是l鸟.getFlySpeed()l鸵鸟.getRunSpeed()l有着不同l结论:IS-A应当是关于行为的。lLSP清晰的指出,OOD中ISA关系是就行为方式而言的,行为方式是可以进行合理假设的,

11、是客户程序所依赖的。IS-A关系的思考(续)l对于动物学家l只关心鸟的生理特征,对他们来说,鸵鸟就是鸟l 对于养鸟人l关心鸟的行为特征,鸵鸟不是鸟l 他们都正确l考虑一个特定设计是否恰当时,不能完全孤立地看这个解决方案,应该根据设计的使用者提出的合理假设来审视。抽象类与具体类具体类3具体类3抽象类1抽象类1抽象类2抽象类2具体类1具体类1抽象类3抽象类3具体类2具体类2LSP原则实施要点l 一个模型,如果孤立的看,并不具有真正意义上的有效性。模型的有效性只能通过它的客户程序来表现。l 有谁知道设计的使用者会做出什么样的合理假设呢?大多数这样的假设都很难预测。事实上,如果试图去预测所有这些假设,

12、我们所得到的系统很可能会充满不必要的复杂性的臭味。l 因此,像OCP原则一样通常最好的办法就是只预测那些最明显的对于LSP的违反情况,而推迟所有其它的预测,直到出现相关的脆弱性的臭味时,才去处理它们。LSP原则实施要点l基于契约设计l 基于契约设计DBC:Design By Contract)。使用DBC,类的编写者能够显式的规定针对该类的契约。客户代码的编写者可以通过该契约获悉可以依赖的行为方式。契约是通过为每个方法声明的前置条件preconditions)和后置条件postconditions)来指定的。要使一个方法得以执行,前置条件必须要为真。执行完毕后,该方法要保证后置条件为真。LSP

13、原则实施要点l在单元测试中指定契约l 也可以通过编写单元测试的方式来指定契约。客户代码编写者会去查看这些单元测试,这样他们就可以知道对于要使用的类,应该做什么合理的假设。LSP原则实施要点l启发式规则l1.派生类中的退化函数l 在基类中实现了f()方法,在派生类中的函数f()就是退化的,派生类中的退化函数并不总表示为违反LSP,但是当存在这种情况时,还是值得注意一下的。l2.从派生类中抛出异常l 在派生类的方法中添加了其基类不会抛出的异常。如果基类的使用者不期望这些异常,那么把它们添加到派生类的方法中就会导致不可替换性。此时要遵循LSP,要么就必须改变使用者的期望,要么派生类就不应该抛出这些异

14、常。LSP原则实施要点 里氏替换原则通俗的来讲就是: 子类可以扩展父类的功能,但不能改变父类原有的功能。下面是几种常用的遵循LSP的实施方法:子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。子类中可以增加自己特有的方法。当子类的方法重载父类的方法时,方法的前置条件即方法的形参要比父类方法的输入参数更宽松。当子类的方法实现父类的抽象方法时,方法的后置条件即方法的返回值要比父类更严格。总结 在许多方面,OCP是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处也就是:灵活性、可重用性以及可维护性)。然而,并 不是说只要使用一种面向对象语言就是遵循了这个原则。对于应用程序中的每个部分都肆意地进行抽象同样不是一个好主意。正确的做法是,开发人员应该仅仅对程 序中呈现出频繁

温馨提示

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

评论

0/150

提交评论