软件设计之美
郑晔
开源项目 Moco 作者
19890 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 42 讲
软件设计之美
15
15
1.0x
00:00/00:00
登录|注册

24 | 依赖倒置原则:高层代码和底层代码,到底谁该依赖谁?

你好!我是郑晔。
上一讲,我们讲了 ISP 原则,知道了在设计接口的时候,我们应该设计小接口,不应该让使用者依赖于用不到的方法。但在结尾的时候,我留下了一个尾巴,说在那个例子里面还有一个根本性的问题:依赖方向搞反了。
依赖这个词,程序员们都好理解,意思就是,我这段代码用到了谁,我就依赖了谁。依赖容易有,但能不能把依赖弄对,就需要动点脑子了。如果依赖关系没有处理好,就会导致一个小改动影响一大片,而把依赖方向搞反,就是最典型的错误。
那什么叫依赖方向搞反呢?这一讲我们就来讨论关于依赖的设计原则:依赖倒置原则。

谁依赖谁

依赖倒置原则(Dependency inversion principle,简称 DIP)是这样表述的:
高层模块不应依赖于低层模块,二者应依赖于抽象。
High-level modules should not depend on low-level modules. Both should depend on abstractions.
抽象不应依赖于细节,细节应依赖于抽象。
Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

依赖倒置原则(DIP)是软件设计中的重要原则之一,强调高层模块不应依赖于低层模块,而是应该依赖于抽象。这一原则的核心在于将依赖关系倒置,让低层模块依赖由高层定义好的接口,从而实现高层模块与低层实现的解耦。文章通过实际代码示例和分析,阐述了依赖倒置原则的重要性和应用方法。作者指出,通过引入一个间接层(抽象)来解决问题,可以让高层模块保持相对稳定,不会随着低层代码的改变而改变。这种做法有利于长期维护和系统的灵活性,能够应对未来可能的变化和替换。文章深入浅出地介绍了依赖倒置原则的概念和实际应用,对于软件设计人员和开发者具有一定的参考价值。文章还提到了与DIP相关的编码规则和DI容器的使用,强调了依赖于抽象的重要性。总之,理解DIP对于构建稳定的模型和框架至关重要,有助于提高代码的质量和可维护性。文章最后提到了防腐层(Anti-Corruption Layer)的适用场景,为读者提供了进一步思考的空间。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《软件设计之美》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(34)

  • 最新
  • 精选
  • Jxin
    防腐层可以解耦对外部系统的依赖。包括接口和参数。防腐层还可以贯彻接口隔离的思想,以及做一些功能增强(加缓存,异步并发取值)。

    作者回复: 没错!

    2020-07-22
    25
  • 魂淡
    老师能不能推荐一些项目,或者框架什么的,去研究和实践老师说的这些理论,听了这么多理论,已经热血沸腾,迫不及待的实践一番!

    作者回复: 如果你想去研究开源项目,我推荐 Spring 框架、Google Guava 和我的 Moco。

    2020-07-28
    2
    13
  • 阳仔
    依赖倒置原则说的是: 1.高层模块不应依赖于低层模块,二者都应依赖于抽象 2.抽象不应依赖于细节,细节应依赖于抽象 总结起来就是依赖抽象(模型),具体实现抽象接口,然后把模型代码和组装代码分开,这样的设计就是分离关注点,将不变的与不变有效的区分开

    作者回复: 总结得好!

    2020-07-22
    6
  • Geek_0315ca
    依赖倒置的关键点在于在高层模块和底层模块之间抽象出一个通用的稳定不变的公共接口。这个接口作为了一个隔板,将稳定部分和易变部分隔离开。这时用到开闭原则-分离关注点,找共性,对修改封闭,对扩展开放。当可变部分扩展业务功能时,只要实现接口方可。接口的粒度需要接口隔离原则和单一职责原则来指导

    作者回复: 嗯,很好的总结。

    2021-02-04
    4
  • 桃子-夏勇杰
    前后端团队经常因为接口变动而延误工期,这个接口到底由谁负责会靠谱一些?前端经常因为后端的接口未实现而延误某个功能,后端则因为对于其他依赖的系统而无法确定和实现接口。

    作者回复: 先确定接口再开发。

    2020-07-30
    4
  • 猪肉怂
    读了郑老师这篇,恍然大悟: 原来防腐层在本质上,是一种依赖倒置。 业务逻辑依赖于防腐层提供的接口,而防腐层则接管了对于外部接口细节的处理,这样当外部系统接口改变的时候,只需要更新防腐层的实现。我觉得这可以理解为系统间的 DIP 原则。 进一步地,「六边形架构」则把这种做法推向极致,把每层都通过 Adapter 与外部进行隔离,无论是访问底层的数据库、缓存基础设施,还是其他的领域服务,全部通过「中间层」进行隔离,让每层都依赖于「抽象」。

    作者回复: 很到位的理解

    2021-06-02
    3
  • 不记年
    感觉TransactionRequest只是存储了数据, 没必要要在抽象出一个接口来吧

    作者回复: 这里的关键在于隔离,虽然它是一个数据类,但在不同的地方扮演了不同的角色。

    2020-07-22
    2
  • KevinSu
    我的理解是高层模块应该依赖高层模块,这样即使底层代码改动也不会影响上层的调用,高层模块依赖底层模块的原因是没有意识到要对底层模块进行抽象后提供给高层使用

    作者回复: 很多人的问题在于没有抽象和实现的区分

    2021-06-17
    1
  • OlafOO
    老师你好,请教下开头的例子,step1和step2如果是接口,还有问题么;像这种流程式的代码还挺常见的

    作者回复: 有问题,你无法确定真的是Step1和Step2,还会不会有Step3,这个设计是不好的。如果你的设计是多个Step,这也许是一个更好的设计。

    2020-07-29
    1
  • private MessageSender sender; void execute() { ... Message message = ...; sender.send(message); 这是啥语言可以这样写?php好像不可以吧?

    作者回复: 这是Java语言的实例代码。

    2020-07-23
    1
收起评论
显示
设置
留言
34
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部