扫码阅读
手机扫码阅读

依赖倒转以及为何要倒转

271 2023-08-22

高层不应该依赖细节,细节应该依赖高层


SOLID原则里面的D,就是依赖倒转原则。我们为何要依赖倒转?在面向对象中如何利用依赖倒转?

所谓依赖,就是我提到了你。在Java或者Python中我import了你,我提到了你就是对你依赖。当我依赖了你后,如果你发生变化,比如更换了实现,我就不得不也跟着更换,这就产生了耦合。

一个典型的Web调用过程,是从前端页面——>控制器——>业务逻辑——>数据库访问DAO——>数据库。这样一个调用关系。如果没有依赖倒转,那么这个调用关系就是依赖关系,调用方依赖被调用方。但我们的业务逻辑是系统的核心,我们不想他依赖任何东西,最好任何东西都依赖他。

这时候依赖倒转就登场了。而依赖倒转在面向过程的语言中非常难以实现,而在面向对象的语言中非常容易。这个重要特性就是多态。我可以声明一个接口,而这个接口可以有多种实现。通过人工或者框架实现的依赖注入,可以将业务逻辑和数据库等实现完全隔离。比如我一个Service业务,声明如下:

其中QueueRepository、QueueDistributeLock都是接口,在QueueServiceImpl中,需要外部数据库、锁的功能,都通过接口来操作。对QueueServiceImpl来说,他没有依赖任何的数据库实现。

在Spring中,我们用依赖注入的方式来注入实现的QueueRepository和QueueDistributeLock

这个是在另外一个Module里面,和业务逻辑不在同一个Module中。这样,我们的业务逻辑和具体实现完全脱离了。

现在我们的实现是通过数据库和Redis实现的。假如有一天我们要更换实现,由于我们的接口同时具有里氏替换原则,我们只需要在注入的时候给QueueServiceImpl不同的实现,就能实现更换,而不需要修改任何业务逻辑。

同时,由于业务逻辑不依赖任何实现,是单纯的POJO。那么业务逻辑就非常容易测试,外部接口可以用Mock模拟行为。而这正是我们TDD需要测试的部分,因而TDD也变得更加容易。

原文链接: http://mp.weixin.qq.com/s?__biz=MzUzMzkxMjE3NQ==&mid=2247483662&idx=1&sn=a27d9fbc62f48d2444dbe32c36edafae&chksm=fa9d8e0ecdea071806cd563005413cf74d046144b1b527a9f471a384dfde651796ccbbdf6a40#rd