面向对象分析设计原则

上传人:cn****1 文档编号:475148349 上传时间:2022-11-07 格式:DOCX 页数:5 大小:16.87KB
返回 下载 相关 举报
面向对象分析设计原则_第1页
第1页 / 共5页
面向对象分析设计原则_第2页
第2页 / 共5页
面向对象分析设计原则_第3页
第3页 / 共5页
面向对象分析设计原则_第4页
第4页 / 共5页
面向对象分析设计原则_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
资源描述

《面向对象分析设计原则》由会员分享,可在线阅读,更多相关《面向对象分析设计原则(5页珍藏版)》请在金锄头文库上搜索。

1、一、单一职责原则(SRP)就一个类而言,应该仅有一个引起它变化的原因。软件设计真正要做的许多内容,就 是发现职责并把那些职责相互分离。测试驱动的开发实践常常会在设计出现臭味之前就迫使 我们分离职责。二、开闭原则(OCP)软件实体(类、模块、函数)应该是可扩展的,但是不可修改的。也就是说:对于扩 展是开放的,对于更改是封闭的。怎样可能在不改动模块源代码的情况下去更改它 的行为 呢?怎样才能在无需对模块进行改动的情况下就改变它的功能呢?关键是抽象!因此在进行 面向对象设计时要尽量考虑接口封装机制、抽象机制和多态技术。该原则同样适合于非面 向对象设计的方法,是软件工程设计方法的重要原则之一。三、替换

2、原则(LSP)子类应当可以替换父类并出现在父类能够出现的任何地方。这个原则是Liskov于1987 年提出的设计原则。它同样可以从Bertrand Meyer的DBC (Design by Contract基于契约设 计)的概念推出。四、依赖倒置原则(DIP)1、高层模块不应该依赖于低层模块。二者都应该依赖于抽象。2、抽象不应该依赖 于细节。细节应该依赖于抽象。在进行业务设计时,与特定业务有关的依赖关系应该尽量 依赖接口和抽象类,而不是依赖于具体类。具体类只负责相关业务的实现,修改具体类不影 响与特定业务有关的依赖关系。在结构化设计中,我们可以看到底层的模块是对高层抽象 模块的实现(高层抽象模

3、块通过调用底层模块),这说明,抽象的模块要依赖具体实现相关 的模块,底层模块的具体实现发生变动时将会严重影响高层抽象的模块,显然这是结构化 方法的一个”硬伤”。面向对象方法的依赖关系刚好相反,具体实现类依赖于抽象类和接口。五、接口分离原则(ISP)采用多个与特定客户类有关的接口比采用一个通用的涵盖多个业务方法的接口要好。 ISP原则是另外一个支持诸如COM等组件化的使能技术。缺少ISP,组件、类的可用性和 移植性将大打折扣。这个原则的本质相当简单。如果你拥有一个针对多个客户的类,为每一 个客户创建特定业务接口,然后使该客户类继承多个特定业务接口将比直接加载客户所需所 有方法有效。以上五个原则是

4、面向对象中常常用到的原则。此外,除上述五原则外,还有一些常用的经 验诸如类结构层次以三到四层为宜、类的职责明确化(一个类对应一个具体职 责)等可供 我们在进行面向对象设计参考。但就上面的几个原则看来,我们看到这些类在几何分布上呈 现树型拓扑的关系,这是一种良好、开放式的线性关系、具有 较低的设计复杂度。一般说 来,在软件设计中我们应当尽量避免出现带有闭包、循环的设计关系,它们反映的是较大的 耦合度和设计复杂化。面向对象之代码复用规则1、对接口编程对接口编程是面向对象设计(OOD)的第一个基本原则。它的含义是:使用接口和同类型的组件通 讯,即,对于所有完成相同功能的组件,应该抽象出一个接口,它们

5、都实现该接口。具体到JAVA中,可 以是接口,或者是抽象类,所有完成相同功能的组件都实现该接口,或者从该抽象类继承。尽量使用接口。 接口只是对象打交道的入口,只有具有继承关系才使用抽象类。2、优先使用对象组合,而不是类继承优先使用对象组合,而不是类继承是面向对象设计的第二个原则。并不是说继承不重要,而是因为 每个学习OOP的人都知道OO的基本特性之一就是继承,以至于继承已经被滥用了,而对象组合技术往往 被忽视了。只有有现实生活中的父子关系才使用继承。相关的设计模式有:Bridge、Composite、Decorator、Observer、Strategy 等。3、将可变的部分和不可变的部分分离

6、将可变的部分和不可变的部分分离是面向对象设计的第三个原则。如果使用继承的复用技术,我们 可以在抽象基类中定义好不可变的部分,而由其子类去具体实现可变的部分,不可变的部分不需要重复定 义,而且便于维护。如果使用对象组合的复用技术,我们可以定义好不可变的部分,而可变的部分可以由 不同的组件实现,根据需要,在运行时动态配置。这样,我们就有更多的时间关注可变的部分。对于对象组合技术而言,每个组件只完成相对较小的功能,相互之间耦合比较松散,复用率较高,通 过组合,就能获得新的功能。4、减少方法的长度通常,我们的方法应该只有尽量少的几行,太长的方法会难以理解,而且,如果方法太长,则应该重 新设计。对此,可

7、以总结为以下原则:三十秒原则:如果另一个程序员无法在三十秒之内了解你的函数做了什么(What),如何做(How)以及为什么要这 样做(Why),那就说明你的代码是难以维护的,必须得到提高;一屏原则:如果一个函数的代码长度超过一个屏幕,那么或许这个函数太长了,应该拆分成更小的子函数; 一行代码尽量简短,并且保证一行代码只做一件事那种看似技巧性的冗长代码只会增加代码维护的难度。5、消除case / if语句要尽量避免在代码中出现判断语句,来测试一个对象是否某个特定类的实例。通常,如果你需要这么 做,那么,重新设计可能会有所帮助。我在工作中遇到这样的一个问题:我们在使用JAVA做XML解析 时,对每

8、个标签映射了一个JAVA类,采用SAX(简单的XML接口 API: Simple API for XML)模型。结 果,代码中反复出现了大量的判断语句,来测试当前的标签类型。为此,我们重新设计了 DTD (文档类型 定义:Document Type Definition),为每个标签增加了一个固定的属性:classname,而且重新设计了每个 标签映射的JAVA类的接口,统一了每个对象的操作:addElement(Element aElement); /增加子元素 addAttribute(String attName, String attValue); 增加属性;则彻底消除了所有的测试当前

9、的标签类型的判断语 句。每个对象通过 Class.forName(aElement.attributes.getAttribute(classname).newInstence();动态创建,6、类层次的最高层应该是抽象类。在许多情况下,提供一个抽象基类有利做特性化扩展。由于在抽象基类中,大部分的功能和行为已经 定义好,使我们更容易理解接口设计者的意图是什么。由于JAVA不允许多继承,从一个抽象基类继承,就无法再从其它基类继承了。所以,提供一个抽象接 (interface)是个好主意,一个类可以实现多个接口,从而模拟实现了 多继承,为类的设计提供了更大的 灵活性。7、尽量减少对变量的直接访问。

10、对数据的封装原则应该规范化,不要把一个类的属性暴露给其它类,而是应该通过访问方法去保护他 们,这有利于避免产生波纹效应。如果某个属性的名字改变,你只需要修改它的访问方法,而不是修改所 有相关的代码。8、拆分过大的类。如果一个类有太多的方法(超过50个),那么它可能要做的工作太多,我们应该试着将它的功能拆分 到不同的类中。9、作用截然不同的对象应该拆分。在构建的过程中,你有时会遇到这样的问题:对同样的数据,有不同的视图。某些属性描述的是数据 结构怎样生成,而某些属性描述的是数据结构本身。最好将这两个视图拆分到不同的类中,从类名上就可 以区分出不同视图的作用。类的域、方法也应该有同样的考虑!如Li

11、nkedList和ListNode SRP,单一职责原则,一个类应该有且只有一个改变的理由。 OCP,开放封闭原则,一个类对扩展开放,而对修改闭合。 LSP,替换原则,所有用基类的地方都可以用派生类来替换。 DIP,依赖倒置原则,依赖于抽象而不是实现。 ISP,接口隔离原则,客户只要关注它们所需的接口。接口尽可能单一,最小化,不要视图抽象一个包含很多功能的接口。六十一条面向对象分析设计的经验原则你不必严格遵守这些原则,违背它们也不会被处以宗教刑罚。但你应当把这些原则看成 警铃,若违背了其中的一条,那么警铃就会响起。(1) 所有数据都应该隐藏在所在的类的内部。(2) 类的使用者必须依赖类的共有接

12、口,但类不能依赖它的使用者。(3) 尽量减少类的协议中的消息。实现所有类都理解的最基本公有接口。如类对象toString而不应该自定义其他接口(5) 不要把实现细节放到类的公有接口中。公有函数是对外接口,具体实现应该尽量用 私有函数做。(6) 不要以用户无法使用或不感兴趣的东西扰乱类的公有接口。(7) 类之间应该零耦合,或者只有导出耦合关系。也即,一个类要么同另一个类毫无关 系,要么只使用另一个类的公有接口中的操作。(8) 一个类应该只表示一个关键抽象。(Java不允许多重继承,解决了这个问题)包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包影响,则 将对包中的所有类产生影

13、响,而对其他的包不造成任何影响.(9) 把相关的数据和行为集中放置。设计者应当留意那些通过get之类操作从别的对象中获取数据的对象。这种类型的行为 暗示着这条经验原则被违反了。(10) 把不相关的信息放在另一个类中(也即:互不沟通的行为)朝着稳定的方向进行依赖.(11) 确保你为之建模的抽象概念是类,而不只是对象扮演的角色。(12) 在水平方向上尽可能统一地分布系统功能,也即:按照设计,顶层类应当统一地共 享工作。(13) 在你的系统中不要创建全能类/对象。对名字包含Driver、Manager System、Susystem 的类要特别多加小心。规划一个接口而不是实现一个接口。类对象实现的功

14、能要单一。(14) 对公共接口中定义了大量访问方法的类多加小心。大量访问方法意味着相关数据和 行为没有集中存放。(15) 对包含太多互不沟通的行为的类多加小心。(16) 在由同用户界面交互的面向对象模型构成的应用程序中,模型不应该依赖于界面, 界面则应当依赖于模型。(17) 尽可能地按照现实世界建模(我们常常为了遵守系统功能分布原则、避免全能类原则 以及集中放置相关数据和行为的原则而违背这条原则)。(18) 从你的设计中去除不需要的类。(19) 去除系统外的类。系统外的类的特点是,抽象地看它们只往系统领域发送消息但并不接受系统领域内其他 类发出的消息。(20) 不要把操作变成类。质疑任何名字是

15、动词或者派生自动词的类,特别是只有一个有 意义行为的类。考虑一下那个有意义的行为是否应当迁移到已经存在或者尚未发现的某个类 中。(21) 我们在创建应用程序的分析模型时常常引入代理类。在设计阶段,我们常会发现很 多代理没有用的,应当去除。(22) 尽量减少类的协作者的数量。一个类用到的其他类的数目应当尽量少。(23) 尽量减少类和协作者之间传递的消息的数量。(24) 尽量减少类和协作者之间的协作量,也即:减少类和协作者之间传递的不同消息的 数量。(25) 尽量减少类的扇出,也即:减少类定义的消息数和发送的消息数的乘积。(26) 如果类包含另一个类的对象,那么包含类应当给被包含的对象发送消息。也

16、即:包 含关系总是意味着使用关系。(27) 类中定义的大多数方法都应当在大多数时间里使用大多数数据成员。(28) 类包含的对象数目不应当超过开发者短期记忆的容量。这个数目常常是6。当类包含多于6个数据成员时,可以把逻辑相关的数据成员划分为一组,然后用一个新 的包含类去包含这一组成员。(29) 让系统功能在窄而深的继承体系中垂直分布。(30) 在实现语义约束时,最好根据类定义来实现。这常常会导致类泛滥成灾,在这种情况下,约束应当在类的行为中实现,通常是在构造函数中实现,但不是必须如此。(31) 在类的构造函数中实现语义约束时,把约束测试放在构造函数领域所允许的尽量深 的包含层次中。(32) 约束所依赖

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 学术论文 > 其它学术论文

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号