首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

依赖倒置原则解读

基本概念

马丁老爷子(Robert C. Martin)在他的书(Agile Software Development, Principles, Patterns, and Practices)中这样描述依赖倒置原则:

A. High-level modules should not depend onlow-level modules. Both should depend on abstractions.

B. Abstractions should not depend upondetails. Details should depend upon abstractions.

翻译成中文就是:

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

B. 抽象不应该依赖于具体实现细节,而具体实现细节应该依赖于抽象。

要理解这个概念,首先要清楚下面几个事情:

高层模块和低层模块

抽象和具体

在软件设计中,低层模块是那些被使用的提供基本功能的组件,就像一块块的积木;高层模块是使用基本组件实现更复杂业务逻辑的模块。高层模块和低层模块是相对的。在架构图中,通常高层模块在上面,低层模块在下面,像下图这样:

依赖反转后变成:

所谓抽象,是说明了做什么(What),而不是怎么做(How),在Java中表现为接口;具体则提供了如何做的细节,在Java中表现为具体实现类。

如何应用DIP实现解耦

接下来用一个简单的例子说明如何应用DIP原则重构代码。

假设有个Blog系统,BlogController负责把前端传过来的数据存入数据库。数据库是SQLite 。示意类图如下:

BlogController.java如下(代码均忽略了无关的细节):

SQLite.java如下:

上面设计违反了DIP的原则。作为上层的BlogController依赖下层的SQLite。如果要更换数据库,BlogController也需要跟着改动。怎么存储数据是存储模块的内部事,为何要牵连BlogController?这种不合理的依赖就是DIP要解决的问题。让我们来改进一下,为了隐藏具体数据库细节,我们对数据库进行抽象,增加Db接口:

看起来不错,是不是?等一下,为什么save方法的参数是blog的字段列表?如果blog字段增加了,接口岂不是要跟着变?为了解决这个问题,我们增加Blog接口:

Db进一步重构为:

这样依赖,即使Blog字段变化,Db接口也不用跟着变了。接口稳定对架构非常重要。相应地,BlogController和SQLite变为:

这时,如果我们把SQLite更换为下面的MySQL,BlogController不会受影响。

最终类图变为:

可以看出,高层的Blog Controller和低层的SQLite、MySQL都只依赖抽象Blog和Db(Blog和Db应该归属高层模块),Db接口不涉及Blog内容细节,符合了DIP的原则。

总结:

依赖倒置是指导代码解耦的一个原则

通过增加一个抽象层来解耦低层和高层

—————END—————

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180109G0Q7LU00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券