依赖倒转原则,迪米特法则,里氏替换原则

抽象不应该依赖细节,细节应该依赖于抽象,意思就是说我们写代码要针对接口编程而不是对实现编程。如电脑中无论主板、CPU、内存、硬盘都是针对接口设计的,PC电脑硬件的发展,和面向对象思想发展是完全类似的。

1.高层模块不应该依赖底层模块,两者应该依赖抽象
2.抽象不应该依赖细节,细节应该依赖抽象

        在面向对象开发中,为了使得常用的代码产生复用,一般会将一些常用的代码写成许许多多的函数的程序库,这样我们在写新项目的时候去调用这些底层的函数就可以了。就好比我们在java项目中打印日志一样,或者servlet容器以及mybatis一样。我们设计一个公共的接口库,然后让具体第三方库去实现这些接口,然后我们在项目中就可以直接通过抽象的接口来调用第三方库提供的底层方法。所以我们要做的就是抽象出公用的接口,并将这些接口和一些虚方法以库的形式依赖到项目中,第三方库实现这些抽象的方法,并将第三方库制作成starter,然后再将其导入到项目中。就上边说的这些来看,我们在做具有同类项性质的starter工程的时候,应该提炼接口,然后按具体的starter的特性去实现具体的功能。

里氏替换原则:子类型必须能够替换他们的父类型。

        在类的继承中,我们知道子类继承了父类,那么子类就可以赋值给父类,但是父类不能赋值给子类。因为子类可以对父类进行修改和对父类的方法进行修改,因此我们可以在不修改父类的情况下对父类的功能进行一定修正,这其实也就是我们上次说的扩展。如此的话扩展从横向来说就是用接口对业务线的扩展,纵向上就是对旧业务线的修正。

        一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的区别。也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变化,简单的说,子类型必须能够替换掉他们的父类

        正是有了里氏替换原则,使得继承复用成为了可能,只有当子类可以替换掉父类,软件单位的功能不受影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。

        正是由于子类型的可替换性才使得使用父类类型的模块在无需修改的情况下可以拓展。

        依赖倒转可以说是面向对象设计的标志,用那种语言编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中的所有依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之就是过程化的设计。

《大话设计模式-程杰》

上述的依赖倒转、里氏替换都是面向对象开发中扩展特性的原则和理念。从业务的广度上我们应该注意实践依赖倒转,从业务深度上我们应该注重里氏替换。

1.概念

  • 依赖倒转原则
1.高层模块不应该依赖底层模块,两者应该依赖抽象
2.抽象不应该依赖细节,细节应该依赖抽象
  • 里式替换原则
子类型必须能够替换他们的夫类型
  • 迪米特法则
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

 2.总结

1.依赖倒置原则:

在Java语言中的表现:

  • 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的
  • 接口或抽象类不依赖于实现类
  • 实现类依赖于接口或抽象类

深入理解:

  • 每个类尽量都要有接口或抽象类,或者抽象类和接口都有: 依赖倒置原则的基本要求,有抽象才能依赖倒置
  • 变量的表面类型尽量是接口或者抽象类
  • 任何类都不应该从具体类派生

2.迪米特法则:

迪米特法则强调以下两点:

  • 从依赖者的角度来说,只依赖应该依赖的对象。
  • 从被依赖者的角度说,只暴露应该暴露的方法。

故在运用迪米特法则时要注意以下 6 点。

  • 在类的划分上,应该创建弱耦合的类。类与类之间的耦合越弱,就越有利于实现可复用的目标。
  • 在类的结构设计上,尽量降低类成员的访问权限。
  • 在类的设计上,优先考虑将一个类设置成不变类。
  • 在对其他类的引用上,将引用其他对象的次数降到最低。
  • 不暴露类的属性成员,而应该提供相应的访问器(set 和 get 方法)。
  • 谨慎使用序列化(Serializable)功能。

3.里氏代换原则:

子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义:

  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  • 子类中可以增加自己特有的方法。
  • 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。(意思子类方法的形参类型要是重载父类方法形参类型的父类,这样调用的才是父类的方法)
  • 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。(即子类重写父类的抽象方法时返回值可以和父类相同也可以是父类抽象方法返回值的子类型)

我们会发现在自己编程中常常会违反里氏替换原则,程序照样跑的好好的。所以大家都会产生这样的疑问,假如我非要不遵循里氏替换原则会有什么后果?

后果就是:你写的代码出问题的几率将会大大增加
 

面向对象六大设计原则

1、“开-闭”原则(Open-Closed Principle,OCP)
2、里氏替换原则(Liskov Substitution Principle,LSP)
3、依赖倒置原则(Dependence Inversion Principle,DIP)
4、接口隔离原则(Interface Separate Principle,ISP)
5、合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)
6、迪米特法则(Law of Demeter,LoD)

你可能感兴趣的:(java,里氏替换原则,依赖倒置原则,迪米特法则)