七个设计原则
面向对象编程有七大原则,即经常提到的Design Pattern,提倡它的根本原因是为了代码复用,增加可维护性。
设计模式就是实现了这些原则,从而达到了代码复用、增加可维护性的目的。因为设计模式就是基于这些原则的实现,所以很有必要了解这些原则,下面主要对面向对象编程的几个原则进行简单介绍。
单一职责原则 ( SRP )
本质:方法的封装
特性:一个功能、一个作用,一个方法。隐藏复杂,暴露简单。降低耦合性。
开闭原则 ( OCP )
本质: 新旧功能分开。原有方法是关闭的,新增的功能是开放的。
理解:在原先代码不变的基础上进行修改。如果一个类(方法/功能),从头到尾都是你自己编写的,是可以从头到尾进行任意调整。如果存在其它人写的。绝对不允许改,否则整体功能架构会被破坏。绝对不允许~~你担不起责任。(想改就要负责任)
里氏替换原则 ( LSP )
本质:继承
原则:任何使用到父类的对象,都可以用子类对象代替。
也就是说,子类对象可以随时随地替换父类,且替换完以后,语法不会报错,业务逻辑不会报错,否则不满足。
业内存在 " 正方形不是长方形,鸵鸟不是鸟" 的问题,主要是应为 业务逻辑上可能存在冲突的问题,导致子类与父类之间违反了里式替换原则
public class A{}
public class B extends A{}
public static void main(String arge[]){
A a = new A();
// 符合里式替换原则,写法
A a = new B();
}
总结:(摘抄)
所谓对象是一组状态和一系列行为的组合。状态是对象的内在特性,行为是对象的外在特性。LSP所表述的就是在同一个继承体系中的对象应该有共同的行为特征。我们在设计对象时是按照行为进行分类的,只有行为一致的对象才能抽象出一个类来。设置长方形的长度的时候,它的宽度保持不变,设置宽度的时候,长度保持不变。正方形的行为:设置正方形的长度的时候,宽度随之改变;设置宽度的时候,长度随之改变。所以,如果我们把这种行为加到基类长方形的时候,就导致了正方形无法继承这种行为。我们“强行”把正方形从长方形继承过来,就造成无法达到预期的结果。鸵鸟非鸟,能飞是鸟的特性,但鸵鸟是不能飞的,我们强行将其归为鸟类,最终导致代码出错。
所有子类的行为功能必须和其父类持一致,如果子类达不到这一点,那么必然违反里氏替换原则。在实际的开发过程中,不正确的派生关系是非常有害的。伴随着软件开发规模的扩大,参与的开发人员也越来越多,每个人都在使用别人提供的组件,也会为别人提供组件。最终,所有人的开发的组件经过层层包装和不断组合,被集成为一个完整的系统。每个开发人员在使用别人的组件时,只需知道组件的对外裸露的接口,那就是它全部行为的集合,至于内部到底是怎么实现的,无法知道,也无须知道。所以,对于使用者而言,它只能通过接口实现自己的预期,如果组件接口提供的行为与使用者的预期不符,错误便产生了。里氏替换原则就是在设计时避免出现派生类与基类不一致的行为。
依赖倒置原则 ( DIP )
原则:上层不能依赖于下层,(上层、下层)都应该依赖于抽象(接口类/抽象类)
UML中存在依赖的关系,依赖倒置更容易通过UML图,加强理解。
错误:每当下层进行变动时,上层也要变
正确:当下层新增一个对象时,上层对象不进行调整。
接口隔离原则 ( ISP )
本质:不要创建一个 “功能很全”的接口
理解:在做接口设计时,不允许将不同类型的方法放在一起。要保证相同类型的方法,放在相同的接口中,形成专门的接口。
最少知道原则(迪米特原则)
本质:封装
理解:在职能中,对于“朋友”以外的对象知道(使用)的越少越好,意思就是将 非朋友的内容封装起来,作为另一个方法中的朋友进行处理。
“朋友”的定义:
1)当前对象本身(this)
2)参数(以参量形式传入到当前对象方法中的对象)
3)当前对象本身的成员变量(当前对象的实例变量直接引用的对象)
4)当前对象本身的集合成员变量(当前对象的实例变量如果是一个聚集,那么聚集中的元素也都是朋友)
5)new 出来的对象(当前对象所创建的对象)
组合大于继承(CARP)
如果父类不是自己写的,谨慎继承,如果是自己写的可以不用考虑。
对于其他人写的“父类”,可以通过组合/聚合 的方式引进来。