面向对象五大原则资料_第1页
面向对象五大原则资料_第2页
面向对象五大原则资料_第3页
面向对象五大原则资料_第4页
面向对象五大原则资料_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

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

文档简介

1、面向对象五大原则面向对象, 原则在写设计模式读书笔记之前,我想先总结一下自己对于面向对象设计五大原则的理解,他们分别是:SRP单一职责原则;OCP开放封闭原则;LSPLiskov替换原则;DIP依赖倒置原则;ISP接口隔离原则。1.   单一职责原则     在敏捷软件开发中,把“职责”定义为“变化的原因”,也就是说,就一个类而言,应该只有一个引起它变化的原因。    在UML与模式应用一书中又提到,“职责”可以定义为“一个类或者类型的契约或者义务”,并把职责分成“知道”型职责和“做”型职责。    其中“做”型职

2、责指的是一个对象自己完成某种动作或者和其他对象协同完成某个动作;“知道”型职责指的是一个对象需要了解哪些信息。如果按照这种方式来定义“职责”的话,就与敏中对单一职责原则的定义不太相符了,所以还是理解为“变化的原因”比较恰当。    这个原则很好理解,但是既然谈到了职责,就不妨再来看看GRASP通用职责分配软件模式(选自UML与模式应用)。按照我自己的看法来讲,在下面 这些职责分配模式中所涉及到的设计问题,是建立在现实世界抽象层次上的设计,从这个层次上进一步细化,才到了设计模式所说的针对接口编程和优先使用组合的 两大原则。    在这个层次上的抽象,一定要

3、按照现实生活中的思维方法来进行,从我们人类考虑问题的角度出发,把解决现实问题的思维方式逐渐转化成程序能够理解的思维方式,绝不允许在这一步考虑程序代码如何实现,那样子的架构就是基于程序实现逻辑,而不是从解决问题的角度出发来实现业务逻辑(参考“面向对象的思维方法”)。    1   专家模式。    在一个系统中可能存在成千上万个职责,在面向对象的设计中,定义对象的交互时,就要做出如何将职责分配给类的设计选择。    专家模式的解决方案就是:把一个职责分配给信息专家掌握了为履行职责所必需的信息的类。  

4、60; 按照专家模式可以得到:一个对象所执行的操作通常是这个对象在现实世界中所代表的事物所执行的操作这恰恰印证了我上面中的说法。    不过使用专家模式的时候,一定要仔细判断什么样的职责是应该只由一个类完成,什么样的职责应该由不同的类协作完成。举一个小小的反例吧,在“思维方法”一文中,提供了一个收发邮件的例子用以说明作者的观点,源码如下所示:1. public class JunkMail 2.         private String head;3.       

5、60; private String body;4.         private String address;5.         public JunkMain( / 默认的类构造器6.         this.head=.;7.         this.body=.;8.        

6、; 9.         public static boolean sendMail(String address 10.         / 调用qmail,发送email11.         12.         public static Collection listAllMail( 13.      &

7、#160;  / 访问数据库,返回一个邮件地址集合14.         15. 复制代码作 者在这里就犯了一个职责分配的错误:上面的head、body和address都是属于邮件自身的属性,但是这个类却有一个叫做sendMail的方法, 错误就在这个方法这里。在现实生活中,我们发送邮件的时候,是通过邮递员来进行的,绝对没有一封信会长上翅膀自己飞到收信人的手中,在程序中也是一样,一 封邮件绝不可能自己把自己发送出去,应该通过某个MailController之类的类来完成这个功能(之所以不命名为MailSender,

8、是因为后面可能还要添加receiveMail等功能)。   2    创建者模式   如果下列条件满足的话,就把创建类A的实例的职责分配给类B的实例:        a        B聚集了A对象        b        B包含了A对象      &

9、#160; c        B记录了A对象的实例        d        B要经常使用A对象        e        当A的实例被创建时,B具有要传递给A的初始化数据(也就是说B是创建A的信息专家)    如果以上条件中不止一条满足的话,那么最好让B聚

10、集或者包含A    创建者模式用于指导对象实例创建任务的分配,基本目的就是找到一个与被创建对象有关联关系的创建者。    3    低耦合度    4    高聚合度    以上两个模式都是在设计过程中要记住的原则,是时时刻刻需要注意的隐含实现目标。    剩下的几种模式要么和以后的话题关系不大,要么在23种模式中有着体现,不再一一赘述。2.       开放封闭原则Software entity should be

11、 open for extension,but closed for modification  依据这个原则,我们在设计的时候,就要考虑设计中什么会发生变化,并且不让这变化影响到设计,当然在这里就会遇到“过度设计”的问题了,而且预测变化对经验的要求比较高,创建抽象所付出的代价也很大,所以只能限定在可能的变化上,仅仅对程序中呈现出频繁变化的部分进行抽象。我们至少应当做到的是:一种可变性不应当散落在代码的很多角落里,而应当被封装在一个对象里面,更不应该和另外一种可变性混在一起。3       Liskov替换原则子类必须能够替换掉它们的

12、父类。另外还有一句话就是:子类具有扩展父类的责任,而不是重写的责任。这个原则在Thinking in Java(the 2nd editon)和Effective Java中均有提及,当时想到的是因为父类是一组子类公共特征的抽象,所以子类理所当然应该可以替换掉自己的父类。后来看了敏捷软件开发中对于这个原 则的阐释,才明白这里所说的抽象,其真正意义应该是对对象行为方式的抽象。也就是说,IS-A关系是就行为方式而言的,即使是在现实生活中看上去具有 IS-A关系的两个对象,如果在程序中它们的行为方式不相同,那么就不应当具有IS-A关系。比如说,正方形和矩形,按照数学概念,正方形应该属于矩形Squar

13、e is a Rectangle。但是,如果在程序中有一个方法,只改变矩形的长,但是不改变矩形的宽,这时候正方形和矩形的行为方式就不相同了,所以在这种情况 下,Square isnt a Rectangle。获取系统行为的基础是用例分析(详见UML和模式应用),各个用例之间的交互过程就是系统行为的触发过程。我们通过用例契约来定义用例实现的目标,描述一个操作执行前后系统的状态变化,并声明该操作的前置条件和后置条件,这样就可以清楚地得到系统行为。上面说的是分析阶段的工作,同样在设计阶段,我们也应该为每一个类制定契约,定义它的行为方式,声明每一个方法的前置条件和后置条件,从而得到对象的行为方式。4.

14、       依赖倒置原则 高层模块不应该依赖于低层模块。二者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。抽象层次包含的是应用系统的商务逻辑和宏观的战略性决定,而具体层次含有的是和实现有关的算法与逻辑,具体层次的代码会经常发生变动,不能避免出现错误。所以便应该是高层的策略设置模块影响低层的细节实现模块,而不是相反。比如说,先制定业务逻辑的规则,再实现数据库操作等等细节。比较合适的模型是:每个较高的层次都为它需要的服务声明一个抽象接口,较低的层次实现这个接口,每个高层类都通过该抽象接口使用下一层。换句话来说,由客户类声明它们需要的服务接口,

15、仅当客户需要时才对接口进行改变,所以改变实现细节的类就不会影响到客户。拿敏中P118中Button和Lamp对象的例子来说,作者举了一个不成熟的设计,如下:1. public class Button2.        private Lamp itsLamp;3.        public void poll(4.               if(/* some condition*/5.   

16、60;                  itsLamp.turnOn(;6.               7.        8. 复制代码作者说,这个例子背后的抽象是检测用户的开/关指令并将指令传给目标对象,而检测用户指令的机制是无关紧要的,目标对象同样也是无关紧要的。我按照作者的分析写了一段程序,如下所示:1. public int

17、erface SwitchableDevice 2.        public void turnOn(;3.        public void turnOff(;4. 5. 6. public class Lamp implements SwitchableDevice7.        public void turnOn(8.               /do s

18、omething9.        10.        public void turnOff(11.               /do something12.        13. 14. 15. public class Button 16.        public void poll(SwitchableDevice device17.               device.turnOff(;18.        19.        public void push(SwitchableDevice device20.   &

温馨提示

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

评论

0/150

提交评论