UML建模语言及工具PPT课件-第六章 面向对象的设计原则.ppt_第1页
UML建模语言及工具PPT课件-第六章 面向对象的设计原则.ppt_第2页
UML建模语言及工具PPT课件-第六章 面向对象的设计原则.ppt_第3页
UML建模语言及工具PPT课件-第六章 面向对象的设计原则.ppt_第4页
UML建模语言及工具PPT课件-第六章 面向对象的设计原则.ppt_第5页
免费预览已结束,剩余53页可下载查看

下载本文档

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

文档简介

uml建模语言及工具,第 6 章面向对象的设计原则 object-oriented design principles,-3-,review: use-case analysis,评估用例,确定迭代周期 在每一次迭代中的每一个用例: 1. 寻找候选对象 获得各类对象清单:实体类、控制类、边界类 2. 描述对象间的交互-顺序图 针对每个事件流,通过顺序图演示用例的实现过程 3. 描述类-类图 完成类图,描绘类图中的关系 重构类图,构造整个系统的分析模型,-4-,学习线路图,-5-,曹操吟诗,话说三国时期,曹操带领百万大军攻打东吴,大军在长江赤壁驻扎,军船连成一片,眼看就要灭掉东吴,统一天下,曹操大悦,于是大宴众文武,在酒席间,曹操诗性大发,不觉吟道:“喝酒唱歌,人生真爽”。众文武齐呼:“丞相好诗!”于是一臣子速命印刷工匠刻版印刷,以便流传天下。,-6-,曹操吟诗,样张出来给曹操一看,曹操感觉不妥,说道:“喝与唱,此话过俗,应改为对酒当歌较好!”,于是此臣就命工匠重新来过。工匠眼看连夜刻版之工,彻底白费,心中叫苦不喋。只得照办。,-7-,曹操吟诗,样张再次出来请曹操过目,曹操细细一品,觉得还是不好,说:“人生真爽太过直接,应改问语才够意境,因此应改为对酒当歌,人生几何?!”当臣转告工匠之时,工匠晕倒!,-8-,曹操吟诗,可惜三国时期活字印刷还未发明,所以类似事情应该时有发生,如果是有了活字印刷。则只需更改四个字就可,其余工作都未白做。实在妙哉。,-9-,结论,第一,要改,只需更改要改的字,此为可维护; 第二,这些字并非用完这次就无用,完全可以在后来的印刷中重复使用,此乃可复用; 第三,此诗若要加字,只需另刻字加入即可,这是可扩展; 第四,字的排列其实有可能是竖有可能是横排,此时只需将活字移动就可做到满足排列需求,此是灵活性好。,软件开发经历了过程式开发,转变为面向对象开发,就如出现了活字印刷 术一样的道理。通过封装、继承、多态把程序的耦合度降低(传统印刷 术的问题就在于所有的字都刻在同一版面上造成耦合度太高所制),用设计 模式使得程序更加的灵活,容易修改,并且易于复用。,-10-,从问题开始!,长方形与正方形 假如我们有一个类:长方形(rectangle) 我们需要一个新的类,正方形(square) 问:可否直接继承长方形?,没问题,因为数学上正方形就是长方形的子类!,-11-,开始设计:正方形,public class rectangle private int width; private int height; public void setwidth(int w) width = w; public int getwidth() return width; public void setheight(int h) height = h; public int getheight() return height; ,public class square extends rectangle public void setwidth(int w) super.setwidth (w); super.setheight (w); public void setheight(int h) super.setwidth (h); super.setheight (h) ; ,-12-,设计方案正确吗?,public static void resize(rectangle r) while (r.getheight() = r.getwidth() r.setheight(r.getheight() + 1); system.out.println(“its ok.“); ,rectangle r1 = new rectangle(); r1.setheight(5); r1.setwidth(15); resize(r1);,rectangle r2 = new square(); r2.setheight(5); r2.setwidth(15); resize(r2);,使用父类(长方形)时,程序正常运行 使用子类(正方形)时,程序陷入死循环 设计出问题了?继承出问题了?,-13-,为什么会出现问题?,违背了面向对象的设计原则!,-14-,面向对象的设计原则,什么是面向对象设计原则? 面向对象设计原则有什么意义? 是指导面向对象设计的基本指导思想 是评价面向对象设计的价值观体系 是设计模式的出发点和归宿,-15-,设计目标,设计目标 可扩展性 (extensibility) 灵活性 (flexibility) 可插入性 (pluggability) ,-16-,设计质量:好的设计,什么是好的设计? 容易理解 容易修改和扩展 容易复用 容易实现与应用 简单、紧凑、经济适用 让人工作起来心情愉快的设计,-17-,设计质量:坏的设计,什么是坏的设计? 僵化性(rigidity):刚性,难以修改,牵一发而动全身 脆弱性(fragility):易碎,牵一发而肝胆俱裂 牢固性(immobility):无法分解成可移植的组件 粘滞性(viscosity),修改设计代价高昂 不必要的复杂性(needless repetition) 晦涩性(opacity):不透明,很难看清设计者的真实意图,-18-,设计质量:培养灵敏的嗅觉,糟糕的设计总是散发出臭味,让人不悦。判断一个设计的好坏,主观上能否让你的合作方感到心情愉悦,是最直观的标准 设计开发人员要培养嗅觉,当你看到uml图或者代码,感到杂乱、繁琐、郁闷的时候,你可能正面对一个糟糕的设计 这种嗅觉是在实践开发中培养起来的,而面向对象设计原则对此加以归纳和总结,-19-,c+中的继承,class a public: void func1(void); ; class b : public a public: void func2(void); ;,main() b b; b.func1(); b.func2(); ;,-20-,虚函数,class shape public: virtual void draw (void) ; ; class circle : public shape public: virtual void draw (void) ; ; class sphere : public shape public: virtual void draw (void) ; ,-21-,虚函数多态,class shape public: virtual void draw (void) ; ; class circle : public shape public: virtual void draw (void) ; ; class sphere : public shape public: virtual void draw (void) ; ,void drawshape(shape *ashape) ashape-draw(); main() shape ashape; circle acircle; sphere asphere; drawshape( ,-22-,纯虚函数,class shape public: virtual void draw (void) = 0; ; class circle : public shape public: virtual void draw (void) ; ; class sphere : public shape public: virtual void draw (void) ; ,-23-,抽象类,当一个类中拥有一个纯虚函数时,这个类就成为了抽象类 抽象类表示一种概念,不可以被实例化,-24-,面向对象的基本设计原则,lsp:liskov替换原则 the liskov substitution principle ocp:开放-封闭原则 the open-close principle srp:单一职责原则 the single responsibility principle isp:接口隔离原则 the interface segregation principle dip:依赖倒置原则 the dependency inversion principle ,-25-,lsp,lsp(the liskov substitution principle, liskov替换原则) “若对于类型s的任一对象o1,均有类型t的对象o2存在,使得在t定义的所有程序p中,用o1替换o2之后,程序的行为不变,则s是t的子类型” 如果在任何情况下,子类(或子类型)或实现类与基类都是可以互换的,那么继承的使用就是合适的。为了达到这一目标,子类不能添加任何父类没有的附加约束 “子类对象必须可以替换基类对象”,-26-,里氏代换原则(lsp),如果一个软件实体使用的是基类的话那么也一定适用于子类,即子类型(subtype)必须能够替换它们的基类型。但反过来的代换不成立。,-27-,里氏代换原则(lsp),如果一个软件实体使用的是基类的话那么也一定适用于子类,即子类型(subtype)必须能够替换它们的基类型。但反过来的代换不成立。,-28-,违背lsp原则,square类针对height、width添加了rectangle所没有的附加的约束(即要求height=width),这样square类(子类)不能完全替换rectangle(父类) 违背了lsp原则 带来潜在的设计问题(使用resize方法时,子类出错!),-29-,怎么办?,在可能的情况下,由抽象类(接口)继承,-30-,抽象类与具体类,只要有可能,不要从具体类继承。 行为集中的方向是向上的(抽象类) 数据集中的方向是向下的(具体类),-31-,解决方案,-32-,is-a关系的思考?,鸵鸟是鸟吗?是 鸵鸟有翅膀,鸟也有翅膀 鸵鸟有喙,鸟也有喙 但是 鸟.getflyspeed() 鸵鸟.getrunspeed() 有着不同,-33-,is-a关系的思考(续),对于动物学家 只关心鸟的生理特征,对他们来说,鸵鸟就是鸟 对于养鸟人 关心鸟的行为特征,鸵鸟不是鸟 他们都正确 考虑一个特定设计是否恰当时,不能完全孤立地看这个解决方案,应该根据设计的使用者提出的合理假设来审视,-34-,ocp,ocp(the open-close principle, 开放-封闭原则) 软件实体(类、模块、函数等)应该是可扩展的,但是不可修改的 特征: 对于扩展是开放的(open for extension) 模块的行为可以扩展,当应用的需求改变时,可以对模块进行扩展,以满足新的需求 对于更改是封闭的(closed for modification) 对模块行为扩展时,不必改动模块的源代码或二进制代码,-35-,ocp的关键在于抽象,ocp的关键在于抽象 抽象技术:abstract class, interface 抽象预见了可能的所有扩展(闭) 由抽象可以随时导出新的类(开),-36-,范例:手与门,如何在程序中模拟用手去开门和关门? 行为: 开门(open) 关门(close) 判断门的状态(isopened),-37-,设计实现,public class door private boolean _isopen=false; public boolean isopen() return _isopen; public void open() _isopen = true; public void close() _isopen = false; ,public class hand public door door; void do() if (door.isopen() door.close(); else door.open(); ,public class smarttest public static void main(string args) hand myhand = new hand(); myhand.door = new door(); myhand.do(); ,-38-,新的需求,需要手去开关抽屉,冰箱?,我们只好去修改程序!,-39-,解决新的需求:修改设计,public class hand public door door; public drawer drawer; void do(int item) switch (item) case 1: if (door.isopen() door.close(); else door.open(); break; case 2: if (drawer.isopen() drawer.close(); else drawer.open(); break; ,public class smarttest public static void main(string args) hand myhand = new hand(); myhand.door = new door(); myhand.do(1); ,手被改了! 主(使用手)程序也被改了!,-40-,符合ocp的设计方案,public interface excutable public boolean isopen(); public void open(); public void close(); ,-41-,新的实现,public class door implements excutable private boolean _isopen = false; public boolean isopen() return _isopen; public void open() _isopen = true; public void close() _isopen = false; ,public class hand public excutable item; void do() if (item.isopen() item.close(); else item.open(); ,public class drawer implements excutable private boolean _isopen = false; public boolean isopen() return _isopen; public void open() _isopen = true; public void close() _isopen = false; ,public class smarttest public static void main(string args) hand myhand = new hand(); myhand.item = new door(); myhand.do(); ,-42-,public class refrigerator implements excutable private boolean _isopen = false; public boolean isopen() return _isopen; public void open() _isopen = true; public void close() _isopen = false; ,新的需求,需要手去开关冰箱?,为冰箱实现excutable接口 不需要修改任何原有的设计和代码,-43-,关于ocp,ocp是ood中很多说法的核心 如果这个原则应用得有效,应用程序就会具有更多的可维护性、可重用性以及可健壮性 lsp是ocp成为可能的主要原则之一 正是子类型的可替换性才使得使用基类类型的模块在无需修改的情况下就可以扩展,-44-,srp,srp(the single responsibility principle, 单一职责原则) 就一个类而言,应该仅有一个引起它变化的原因 有关类的职责分配问题,是面向对象设计中最重要的基本原则,“a critical, fundamental ability in ooa/d is to skillfully assign responsibility to software components.” craig larman,-45-,srp本质,srp体现了内聚性(cohesion) 内聚性:一个模块的组成元素之间的功能相关性 类的职责定义为“变化的原因”,每个职责都是变化的一个轴线; 当需求变化时,该变化会反映为类的职责的变化 如果一个类承担了多于一个的职责,那么引起它变化的原因就会有多个,-46-,违反srp的案例,rectangle类可能会因为两方面的原因而变化:计算几何方面的原因和用户界面设计方面的原因。其中只一发生变化之后,必须修改rectangle类,而这种修改则可能导致另一个应用程序出错 除此之外,违反srp还会带来物理依赖的缺点。,-47-,解决方案,增加新的类,使得每个类仅有一个职责,-48-,isp,isp( the interface segregation principle,接口隔离原则) 客户不应该依赖他们不用到的方法,只给每个客户它所需要的接口 为了避免

温馨提示

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

评论

0/150

提交评论