依赖反转原则
依赖反转原则
依赖反转原则(Dependency Inversion Principle
,DIP
),也称为依赖倒置原则。
英文描述:
1 | High-level modules shouldn’t depend on low-level modules. Both modules should depend on abstractions. |
中文翻译:
1 | 高层模块(high-level modules)不要依赖低层模块(low-level)。高层模块和低层模块应该通过抽象(abstractions)来互相依赖。 |
一、如何理解“依赖反转”?
依赖反转原则的设计理念:
- 相对于细节的多变性,抽象的东西要稳定的多
现实中,经常存在这么一种场景:
- 整体流程是基本不变的,但是细节实现可能会发生变化
比如说,Tomcat 容器和部署的应用程序。
从调用上来说,Tomcat 会调用应用程序,所以 Tomcat 依赖于应用程序:
1 | Tomcat ---> 应用程序 |
但是如果 Tomcat 依赖于某个应用程序的具体实现,它就不可能是一个通用的容器。
所以现实中,Tomcat 和应用程序实际是依赖于同一个抽象 Servlet:
1 | Tomcat ---> Servlet <--- 应用程序 |
这种将低层抽象出来一层,作为公共依赖的方式,就是依赖反转。
低层的应用程序反过来依赖了 Servlet 这个中间层。
反转的意思是:
- 低层根据高层的调用方式,抽象出调用接口,提供给高层
这是一种反向思考的方式:
- 正常来说,都是先设计的低层接口,然后高层去调用低层接口
- 但依赖反转的思想则是,根据高层的调用,从低层抽象出一层
依赖反转实际是低层反转依赖公共中间层的意思。
二、为什么要“依赖反转”?
依赖反转的目的和作用:
- 低层次模块更加通用,适用性更广
- 高层次模块没有依赖低层次模块的具体实现,方便低层次模块的替换
一般来说,依赖反转原则主要用于指导框架的设计。
框架属于高层,实现细节则是属于低层。
三、如何实现“依赖反转”?
很多时候,不需要用到依赖反转原则。
像平时的业务开发,高层代码直接调用低层代码是很常见的事情。
依赖反转原则主要适用于这样的场景:
- 高层的结构和流程基本不变,但是低层是可变的
- 或者说整体流程是固定不变的,但是细节实现是可变的
依赖反转原则在设计框架时尤其有用,其他的普通情况反而不怎么用到。
依赖反转的实现也很简单:
- 将低层抽象出一层中间层,然后高低层都依赖于这个中间层
这种实现方式,在重构代码时可能会经常用到。