依赖倒置原则(Dependence Inversion Principle,DIP)是指设计代码结构时,高层模块不应该依赖低层模块,二者都该依赖其抽象。即抽象不该依赖细节,细节应该依赖抽象。通过依赖倒置,可以减少类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性,同时能够降低对系统修改时带来的风险。
好了晕车了对嘛,来看一段代码。还是以之前的卖出去的书为例,创建一个类IRead:
/**
* @Author: zhouzhen
* @email: zhouzhen0517@foxmail.com
* @Description 我爱读书,读书让我快乐
* @Date: Create in 10:22 2020/4/9
*/
public class IRead {
public void readJavaBook(){
System.out.println("我正在看Java的书,我可真棒!");
}
public void readPythonBook(){
System.out.println("我正在看Python的书,我可真棒!");
}
}
调用一下
public static void main(String[] args) {
IRead iRead = new IRead();
iRead.readJavaBook();
iRead.readPythonBook();
}
书籍是人类进步的阶梯,看书是会上瘾的。随着求知欲的提升,我现在还想看AI相关的书。这个时候,因为业务需求的扩展,需要从低层到高层依次修改代码,要在IRead类中添加readAIBook方法,同时在main方法中添加调用。在真正的业务环境中,系统往往十分庞大,这样的由底到顶的修改实际上是非常不稳定的,对代码的修改也容易带来意想不到的风险。
接下来我们对代码架构进行优化来解决这个问题,首先创建一个看书的抽象接口Read:
/**
* @Author: zhouzhen
* @email: zhouzhen0517@foxmail.com
* @Description 看书的抽象接口
* @Date: Create in 10:37 2020/4/9
*/
public interface Read {
void readBook();
}
接下来编写ReadJava类
/**
* @Author: zhouzhen
* @email: zhouzhen0517@foxmail.com
* @Description
* @Date: Create in 10:40 2020/4/9
*/
public class ReadJava implements Read {
public void readBook() {
System.out.println("我正在看Java的书,我可真棒!");
}
}
编写ReadPython类
/**
* @Author: zhouzhen
* @email: zhouzhen0517@foxmail.com
* @Description
* @Date: Create in 10:42 2020/4/9
*/
public class ReadPython implements Read {
public void readBook() {
System.out.println("我正在看Python的书,我可真棒!");
}
}
对之前的IRead类进行修改:
/**
* @Author: zhouzhen
* @email: zhouzhen0517@foxmail.com
* @Description 我爱读书,读书让我快乐
* @Date: Create in 10:22 2020/4/9
*/
public class IRead {
public void read(Read read) {
read.readBook();
}
}
调用一下
public static void main(String[] args) {
IRead iRead = new IRead();
iRead.read(new ReadJava());
iRead.read(new ReadPython());
}
再回头看之前的业务需求。不管我再怎么热爱学习,对于新书,只需要新建一个看书的类,通过传参的方式来学习,而不需要再去修改底层代码。实际上这就是我们非常熟悉的方式,依赖注入。注入的方式还有构造器方式和Setter方式,这里不做赘述。
总结
以抽象为基准比以细节为基准搭建起来的架构要稳定很多,因此在拿到需求的时候,要面向接口编程,先顶层再细节的设计代码结构。
文章参考
《Spring5核心原理》〔中〕谭勇德(Tom)