设计模式(三)——面向对象设计原则

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/sinat_21107433/article/details/102578436

设计模式需要遵循基本的软件设计原则。可维护性(Maintainability)和可复用性(Reusability)是衡量软件质量的重要的两个属性:

  • 可维护性:软件能够被理解、改正、适应及扩展的难易程度
  • 可复用性:软件能够被复用的难易程度

面向对象设计的原则是支持可维护性复用,一方面需要实现设计方案或代码的复用,另一方面要保证系统易于扩展和修改,具有良好的可维护性。面向对象设计原则蕴含在各个设计模式中,是学习设计模式的基石,也是用于评价某个设计模式效果(Consequence)的重要指标。常见的面向对象设计原则包括:单一职责原则、开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、合成复用原则、迪米特法则。

1.单一职责原则

单一职责原则:

定义1:一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中

定义2:就一个类而言,应该仅有一个引起它变化的原因。

首先需要知道两个原则:高内聚低耦合

高内聚:内聚是对软件系统中元素职责相关性和集中度的度量。如果元素具有高度相关的职责,除了这些职责内的任务,没有其它过多的工作,那么该元素就具有高内聚性;反之则成为低内聚性。

低耦合:耦合是软件结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据

单一职责原则用于控制类的力度大小。软件设计过程中,如果一个类承担的职责越多,那么它被复用的可能性越小。(为什么?想想,如果一个类有许多接口,另一个类想复用其中一两个接口,还不如重新实现!)。另一方面,如果一个类承担的职责越多,各个职责耦合在一起,修改其中一个职责可能“牵一发而动全身”。因此,应该将这些职责进行分离,不同的职责封装在不同的类中。 

2.开闭原则

开闭原则:软件实体应对扩展开放,对修改关闭。

开闭原则指软件实体(一个软件模块、一个由不同类组成的局部结构或一个独立的类) 应该在不修改原有代码的基础上进行扩展。软件设计过程中,需求可能会随时变化,需要根据需求扩展已有的设计。如果原有的设计符合开闭原则,那么扩展起来就比较安全(不会影响原有功能,稳定)和方便(易于扩展)。开闭原则的关键在于抽象化。可以为系统定义一个相对较为稳定的抽象层,将不同的实现行为放到具体的实现层中完成。

扫描二维码关注公众号,回复: 7594750 查看本文章

举个例子:要设计一个计算器的类Computer,包含加、减两个功能,很自然的想法是在类Computer里声明并实现Add和Sub两个方法。那么如果要求再增加乘法功能,是不是要在Computer里增加Mul的方法呢?这就违背了开闭原则。

3.里氏代换原则

历史替换原则:所有引用基类的地方必须能透明地使用其子类的对象。

 在软件中,如果用子类对象来替换基类对象,程序将不会产生任何异常和问题,反过来不成立。为什么?很好理解,子类继承自基类,基类有的成员方法和成员属性,子类全都有;而子类可以增加新的方法和属性,所以反过来不成立。

里氏代换原则的指导意义在于:尽可能地使用基类类型来对对象进行定义,而在运行时再确定子类类型,然后用子类对象替换父类对象设计时应将父类设计为抽象类或者接口,子类继承父类并实现在父类中声明的方法;运行时子类实例(对象)替换父类实例(对象),可以很方便地扩展系统功能。

4.依赖倒转原则

依赖倒转原则:高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。

 什么是高层,什么是低层呢?它们指的是继承(派生)中的基类子类关系,基类或者越抽象的类,层次越高。简单说,依赖倒转原则要求针对接口编程,不要针对实现编程

依赖倒转原则要求再程序代码中传递参数时,或在关联关系中,尽量引用层次高的出现层类,即使用接口或抽象类来声明变量类型、参数类型声明、方法返回类型声明,以及数据类型转换等,而不要使用具体类来做这些事情。(其实这一点也符合里氏代换原则的指导意义,即对一个方法而言,返回基类的地方一定可以返回子类)。同样,依赖倒转原则设计的关键也在与抽象化设计。

5.接口隔离原则

接口隔离原则:客户端不应该依赖那些它不需要的接口。

当一个接口太大时,应该将它根据需要分割成多个更细小的接口,每个接口仅承担一个相对独立的角色或功能,使用该接口的客户端仅需知道与之相关的方法即可。 但是,接口不能过小,否则系统中接口太多,不利于维护。一般而言,在接口中仅包含为某一类用户定制的方法即可。

6.合成复用原则

合成复用原则:优先使用对象组合,而不是通过继承来达到复用的目的。

 根据UML类图关系,合成复用原则指导在软件设计时,优先使用关联、聚合和组合关系,尽量少用泛化(继承)。对象组合可以使系统更加灵活(黑箱复用),降低类与类之间的耦合度,一个类的变化尽可能不影响其他类(父类和子类耦合度高不高?)。如果要使用继承,则需考虑里氏代换原则和依赖倒转原则。继承关系会破坏系统的封装性,会将基类的实现细节暴露给子类(白箱复用),如果基类发生改变,那么子类的实现也不得不改变。

7.迪米特法则

 迪米特法则:每一个软件单位对其他单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位

迪米特法则要求一个软件实体应当尽可能少地与其他实体发生相互作用。如果一个系统负荷迪米特法则,那么当修改其中某一个模块时就会尽量少地影响其他模块。应用迪米特法则可以降低系统的耦合度。在类的设计上应该注意以下几点:在类的划分上应尽量创建松耦合的类,类之间的耦合度越低,越有利于复用;类的结构设计上,每一个类都应该降低其成员变量和成员函数的访问权限。


欢迎关注知乎专栏:Jungle是一个用Qt的工业Robot

欢迎关注Jungle的微信公众号:Jungle笔记

猜你喜欢

转载自blog.csdn.net/sinat_21107433/article/details/102578436