前言:
我们现在学习的是面向对象的程序设计,而可维护,可复用都是以面向对象设计原则为基础的,遵循这些设计原则,
我们可以有效的提高系统的复用性,维护性,扩展性;在这些原则的基础上,我们使我们可以设计出更加清晰,更加
简洁的系统。
内容:
一、单一职责原则 :就一个类而言,应该仅有一个引起它变化的原因。
分析:
(1)一个类(大到模块,小到方法)的职责过多,那么这个类被复用的可能性就低。因为一个类的职责太多了,一个职责变化很有可能影响到其他职责的运行,这样就则加了耦合性,不利于扩展。因此我们应该将不同的职责封装到不同的类中,减少不同职责之间的影响,从而实现高内聚,低耦合。
(2)类的职责包括:数据职责和行为职责。数据职责可以通过属性来体现;行为职责则通过方法来体现。
(3)单一职责原则是实现高内聚,低耦合的指导方针,它是比较简单但又很难运用好的原则。因为职责的发现和分
离这个过程,一般人很难去发现和运用。
例如:如果数据结构和打印数据表都放在Database类中,这样就显得一个类的职责太多。因为打印数据可以分为部分数据和全部数据,只有我们把数据结构和打印数据表分隔开,这个类才能更好的被复用,从而增加了类的复用性。
二、开放-封闭原则:对于软件实体(类,模块,函数等等)应该对扩展开发,对修改关闭。
分析:
(1)为了满足市场需要,增加一个新的功能,我们不能去修改已有的代码,而让软件具备一定的功能去适应新的需
求 ;而是应该在原来抽象的基础上去通过扩展也就是增加子类的方式去增加新的功能区适应社会的需要。
(2)实现开闭原则的关键就是抽象化。众所周知越抽象越容易扩展,但是这是我们在保证系统设计框架稳定的前提
下进行的扩展的;允许扩展的是实现类,抽象类和接口是不允许修改的。
(3)开闭原则是面向对象设计中“可复用设计”的基石原则,是面向对象设计中最重要的原则之一。里氏代换,依
赖倒转,接口隔离都可以看做是开闭 原则的实现。
例如:模板方法模式和观察者模式都是开闭原则的极好体现。都是在保证原来代码的基础上,保证修改的关闭;通过增加子类来达到扩展新的功能,即对外是开放的。
三、里氏代换原则:子类必须能够替换掉他们的父类型。
分析:
(1)在软件里面,父类替换成他的子类,程序的行为没有变化。而反过来,一个软件使用的是一个子类,那么不一
定能够使用父类。
(2)里氏代换原则主要出发点是继承基础上的抽象和多态。抽象的是父类,多态的是子类。
方法的重写:子类继承父类的相同的方法,输入参数一样,但是做出有别于父类的操作,要覆盖父类方法。---相同
参数,相同返回值,不同的实现。
方法的重载:同样的方法能够根据传入参数的不同,做出不同的处理。---不同的参数,不同的返回值(构造函数里
面经常用到)
例如:
鸟和企鹅就是一个典型。鸟可以飞,而企鹅不会飞,因此不能用企鹅来里氏代替大多数鸟来实现飞这个方法。
正方形和长方形也是一个典型。正方形是长度相等的长方形,这是大家公认。让正方形来里氏代换长方形这也是顺理
成章的事。
四、依赖倒转原则:高层模块不应该依赖低层模块,两个都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。
分析:
(1)抽象不应该依赖细节,细节应该依赖抽象。也就是说要针对接口编程,不要对实现编程。
(2)依赖倒转原则的核心思想是面向接口编程。
例如:电脑上的键盘,鼠标,他们都用的usb接口,如果键盘坏了,我们 就可以换一个键盘;鼠标坏了就可以换一个
鼠标;而不是键盘或鼠标坏了就去换一台电脑,这样就显的太不合理了。只要我们将这个接口编程好,无论是鼠标还
是键盘坏了,我们就可以立马换一个鼠标或键盘,从而更好的达到复用这个效果。
五、迪米特法则(最少知识原则):如果两个类不必彼此直接通信,那么这两个类就不应该发生直接的相互作用。如果其中一个类需要调用另一类的某一个方法的话,可以通过第三者转发这个调用。
分析:
(1)在类的结构设计上,每一个类都应当尽量降低成员的访问。不要和陌生人说话,只跟自己的朋友通信。
(2)迪米特法则其根本思想是强调了类之间的松耦合(解耦)。每一个类应尽量减少对其他类的依赖,,尽可能独
立,弱耦合能使类的复用率提高。
例如:外观模式。系统中的类尽量不要与其他类之间相互作用,耦合度降低了,扩展的时候就不用去修改这些类了,
这样维护的成本才会降低。
六、合成/聚合复用原则:尽量使用合成/聚合,尽量不要使用类继承。
聚合(无生命的):表示一种弱的“拥有”关系,体现的是A可以包含B对象,但B对象不是A对象的一部分;
合成(有生命的,共存亡):表示的是一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周
期一样。
分析:
(1)组合/聚合可以使系统更加灵活,使类与类的耦合度降低。一个类的变化对其他类造成的影响相对来说比较小,因此一般首选组合/聚合,其次才考虑继承。滥用继承往往增加系统构件和维护的难度,不利于扩展维护,因此要慎
用继承。
(2)组合/聚合原则和里氏代换相铺相成,两者都是实现“开闭原则”的规范。
例如:手机品牌和手机软件,这两者往往采用聚合,从而减少耦合性,达到易扩展的效果。
总结:
开闭原则、里氏转换、依赖倒转原则一般会同时出现:开闭是目标,里氏是基础,依赖是手段,它们相辅相成,相互补充,目标一致,只是分析问题时所站角度不同。
单一职责告诉我们实现类要职责单一;里氏转换告诉我们不要破坏继承体系;依赖倒置告诉我们要面向接口编程;迪米特法则告诉我们要降低耦合,开闭是总纲,告诉我们对扩展开放,对修改关闭。