一、面向对象六大原则
1、单一职责原则
通俗的讲:单一职责原则可以拆成单一、职责两部分,单一代表一个,只有一个,职责代表要负责的事情。用在Java中来讲,一个类仅要负责一个事情(一个类只负责一项职责)
官方(正式)说法:不要存在多余一个导致类变更的原因/就一个类而言,应该仅有一个引起他变化的原因
为什么要使用单一职责原则?
如果一个类承担的职责过多,就会吧这些职责耦合到一起,一个职责的变化可能会削弱或抑制这个类完成其他职责的能力。当这个类发生变化的时候,这种耦合性可能会导致某些职责不能正常使用。
出现原因和解决方案:存在一个类A,类A拥有职责1和职责2,当职责1发生变化需要修改类A,但是有可能会导致职责2出现未知问题,因此出现单一职责原则,建立类A和类B,分别去处理职责1和职责2,这样使职责1与职责2相互隔离,修改类A不会影响到职责2,于此同理,减少故障发生风险。
单一职责的优点是什么?
- 降低类的复杂度,一个类负责一项职责、逻辑清晰明了
- 因职责逻辑清晰,因此可读性提高
- 维护性相应提高
- 变更引起风险降低,一个类修改只对其职责有影响,对其他类、职责无影响
注:单一职责思想不仅仅适用于类,同样适用于方法
2、里氏替换原则
里氏???:1988年,麻省理工学院的一位姓里的女士提出的,因此叫做了里氏替换原则
通俗的讲:子类可以扩展父类的功能,但是不能改变父类原有的用途,也就是说,在子类继承父类的时候,除了添加新的方法完成新增的功能之外,尽量不要重写父类的方法(子类重写父类方法时,可以改变方法具体行为,而不应该改变)
也可以这么说,子类完全可以替换掉他的父类型,软件单位中的功能不收影响,父类才是真正的被服用,而子类能够在父类基础上添加新的行为。
官方定义:所有引用基类的地方必须能透明的使用其子类对象
总结:
- 子类可以实现父类的抽象方法,但不能覆盖父类非抽象方法
- 子类可以增加自己特有的方法
- 当子类重载父类方法时,方法的入参要比父类的更加宽松,如父类需要三个入参,子类两个即可
- 当子类方法实现父类方法时(重写、重载或实现),方法的后置条件(方法返回值)要比父类更加严格或相等
里氏替换原则的优点?
- 约束继承泛滥
- 加强程序健壮性,变更时做到更好的兼容性,提高程序维护性,可扩展性,降低需求变更引入的风险
3、开闭原则
通俗的讲:软件系统只对扩展开放,对修改关闭(用抽象构建框架,用实现扩展细节)
出现原因和解决方案:在软件生命周期,因为变化、升级、维护等原因对软件原有代码进行修改时,可能会给旧代码引入错误。因此,当软件需求发生变化时,尽量通过扩展的形式来实现变化,而不是通过修改已有的代码来实现。
4、依赖倒置原则
通俗的讲:高层模块不应该依赖低层模块,两者都应该依赖抽象,抽象不应该依赖细节,细节应该依赖抽象。
要针对接口(抽象)编程,而不是针对实现编程,程序所有依赖关系终止于接口(抽象),同样目的为解决开闭原则而产生的,对修改关闭,对扩展打开。
优点:降低类与类之间耦合性,提高系统稳定性、代码可读性、可维护性且降低修改代码而带来的风险
5、接口隔离原则
接口隔离通俗来讲,使用多个"专门"的接口,而不是使用单一的一个接口,客户端不应该依赖他不需要的接口,与单一职责原则前后呼应,一个类、一个接口、一个方法仅负责单一的用途。
设计接口时应注意:
- 一个类对另一个类的依赖应该建立在最小接口上
- 建立单一接口,不要建立庞大冗余的接口
- 尽量细化接口,接口中方法尽量少(不是越少越好,适度,最好按照单一原则,一个接口仅负责自己的职责(用途、行为))
接口隔离应符合“高内聚,低耦合“设计思想
6、迪米特法则(最少知道原则)
一个对象应该对其他对象保持最少了解,尽量降低类与类之间的耦合。迪米特法则主要强调只与朋友交流,不与陌生人对话,出现在成员变量、方法输入输出参数的类可以被称为朋友类,方法体内部的类不属于朋友类。
两个类不必直接通信,那么这两个类就不应当发生直接相互作用,如果其中一个类需要调用另一个类的某个方法,可以通过第三者去转发调用。
目的为了类之间松耦合,类之间耦合越弱,越利于复用,弱耦合的类被修改不会对有关系的类造成波及。在类的结构设计上,每个类都应当降低成员访问权限。
7、合成/聚合复用原则
合成聚合复用指的是尽量使用对象组合或对象聚合的方式实现代码复用,而不是用继承关系达到代码复用的目的。
合成复用可以使系统更加灵活,降低类与类之间的耦合度,一个类变化对其他类造成影响比较小。
继承,要把所有实现细节暴露给子类。
聚合是一种弱拥有的关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分
合成是一种强拥有,体现严格的部分和整体的关系,部分和整体的生命周期一样。
优先使用对象的合成/聚合将有助于保持每个类的封装,类和类继承层次会保持较小规模