设计模式之禅笔记--面向对象设计六大原则之三

时间:2022-08-19 17:26:00

第三章   依赖倒置原则(DIP)

定义:

依赖倒置原则( Dependence Inversion Principle,DIP) 这个名字看着有点别扭,“依赖”还“倒置”, 这到底是什么意思? 依赖倒置原则的原始定义是:

Highlevel modules should not depend upon low level modules. Both should depend uponabstractions. Abstractions should not depend upon details. Details shoulddepend upon abstractions.

定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。

问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。

解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。

例子:

设计模式之禅笔记--面向对象设计六大原则之三设计模式之禅笔记--面向对象设计六大原则之三

解释:

在实际编程中,我们一般需要做到如下3点:

  • 低层模块尽量都要有抽象类或接口,或者两者都有。
  • 变量的声明类型尽量是抽象类或接口。
  • 使用继承时遵循里氏替换原则。

       依赖倒置原则的核心就是要我们面向接口编程,理解了面向接口编程,也就理解了依赖倒置。

注意 设计是否具备稳定性, 只要适当地“松松土”,观察“设计的蓝图”是否还可以茁壮地成长就可以得出结论, 稳定性较高的设计,在周围环境频繁变化的时候, 依然可以做到“我自岿然不动”。

注意 在Java中, 只要定义变量就必然要有类型, 一个变量可以有两种类型: 表面类型和实际类型, 表面类型是在定义的时候赋予的类型,实际类型是对象的类型, 如zhangSan的表面类型是IDriver,实际类型是Driver。

 

一个通俗的规则: 接口负责定义public属性和方法, 并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现, 实现类准确的实现业务逻辑, 同时在适当的时候对父类进行细化。

到底什么是“倒置”呢? 依赖正置就是类间的依赖是实实在在的实现类间的依赖,也就是面向实现编程, 这也是正常人的思维方式, 我要开奔驰车就依赖奔驰车, 我要使用笔记本电脑就直接依赖笔记本电脑, 而编写程序需要的是对现实世界的事物进行抽象,抽象的结果就是有了抽象类和接口, 然后我们根据系统设计的需要产生了抽象间的依赖代替了人们传统思维中的事物间的依赖, “倒置”就是从这里产生的

依赖的三种写法

1.      构造函数传递依赖对象

在类中通过构造函数声明依赖对象,按照依赖注入的说法, 这种方式叫做构造函数注入。

2.      Setter方法传递依赖对象

在抽象中设置Setter方法声明依赖关系, 依照依赖注入的说法, 这是Setter依赖注入,按照这种方式的注入。

3.      接口声明依赖对象

在接口的方法中声明依赖对象,该方法也叫做接口注入。

最佳实践

● 每个类尽量都有接口或抽象类, 或者抽象类和接口两者都具备

● 变量的表面类型尽量是接口或者是抽象类

● 任何类都不应该从具体类派生(项目维护除外,因为修复行为, 通过一个继承关系, 覆写一个方法就可以修正一个很大的Bug, 何必去继承最高的基类呢?)‘

● 尽量不要覆写基类的方法

● 结合里氏替换原则使用

 

依赖倒置原则是6个设计原则中最难以实现的原则, 它是实现开闭原则的重要途径, 依赖倒置原则没有实现, 就别想实现对扩展开放, 对修改关闭。在项目中, 大家只要记住是“面向接口编程”就基本上抓住了依赖倒置原则的核心。