依赖倒置 (DIP)

用户头像
Lane
关注
发布于: 2020 年 06 月 17 日
依赖倒置(DIP)

架构0期-W2-实战作业

请描述什么是依赖倒置原则,为什么有时候依赖倒置原则又被称为好莱坞原则?

请描述一个你熟悉的框架,是如何实现依赖倒置原则的。

一、什么是依赖倒置原则(DIP)?

1.高层模块不应该依赖于低层模块,二者都应该依赖于抽象。

2.抽象不应该依赖于细节,细节应该依赖于抽象。

3.层次化角度来说,就是高层决定低层,高层被重用。

4.依赖倒置原则更像是一种应该养成的编程习惯,它要求你面向接口编程。

这里提到的“高层模块”和“低层模块”,从调用链的角度来说就是调用者属于高层,被调用者属于低层。

举个例子:

controller通常都是依赖service里的方法,依赖倒置的意思就是controller层应该依赖接口,也就是controller来定义接口,然后service去实现这些接口,也就是依赖倒置了。

二、依赖倒置的例子

以golang的Gin框架为例,我的体会是它使用了IoC(Inversion of Control)和DIP(Dependency Inversion Principle)。

以一个简单的例子开始,如下是一个最简单的http请求响应+server的代码。

package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message1": "hello world1"})
}, func(c *gin.Context) {
c.JSON(200, gin.H{"message2": "hello world2"})
})
r.Run()
}

gin.Default()函数返回的是一个Engin指针,而后续的func函数是类似语句的Web业务函数,由此我们很形象的就能认为Gin框架是高层模块,而具体的Web应用程序就是底层模块,不考虑DIP,就应该是高层依赖底层框架,就像下面这样。

但这样是明显不可行的,假如Web程序改动了涉及到了Gin了该怎么办?Gin官方是不可能给我们改的,要改也是我们自己改。把DIP加进去考虑这个问题就是应该是像下面这样

Gin和Web应用程序同时依赖与抽象才能隔离变化,这也就刚好符合了DIP的原则。



这个我在Gin的源码中找到的DIP的依据,应用程序r.get都是依赖于IRouter接口,而IRouter最终依赖的是net/http,gin.Context最终依赖的也是net/http,因此可以确定我上面的分析。





再说说IoC

r.Get是在将“Web应用程序”的逻辑注入到Gin(容器)中,func(c *gin.Context)函数就将自己的HttpHandler注册进入Gin这个容器中,Gin在截获到ping这个Get请求的时候会主动调用func这个后续的方法,这个过程也就是Ioc的过程,也可以形象的理解为它非常符合好莱坞原则,即(Web应用程序)你不要联系我(Gin),我(Gin)会主动找你(Web应用程序),



综上所述,Gin符合了两个面向对象的设计原则,IoC(Inversion of Control)和DIP(Dependency Inversion Principle)。

三、为什么有时候依赖倒置原则又被称为好莱坞原则?

好莱坞原则是这样描述的

Don't call me,I'll call you. 别打电话给我,有事我会打电话给你。

好莱坞原则在IoC(Inversion of Control) 控制反转中得到了很好的体现,IoC就是由容器来负责控制对象的生命周期和对象间的关系

通俗来将就是所有的类都在容器登记,类是个什么东西,需要什么东西都告诉容器,容器会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由容器来控制,也就是说控制对象生存周期的不再是引用它的对象,而是容器。

这体现了好莱坞原则,类不用主动找容器要你需要的东西,在容器需要你(类)的时候会主动找你的,即低层应该只管好自己的工作(具体实现),而高层自有它自己的工作

依赖倒置原则是指高层不依赖低层只依赖抽象,低层也依赖抽象。

综上所述,好莱坞原则和依赖倒置还是有不同点的,相同点是他们都是描述高层与下层之间关系的,都是为了解决类之间的紧耦合而总结出来的



用户头像

Lane

关注

还有梦想 2018.07.05 加入

还未添加个人简介

评论

发布
暂无评论
依赖倒置(DIP)