控制反转与依赖注入 (1) - 先区分好 IoC 和 DI 是什么

未匹配的标注

手握设计模式宝典 - 控制反转与依赖注入 (1) - 先区分好 IoC 和 DI 是什么

Design-Pattern - Inversion-Of-Control and Dependency-Injection

  • Title: 《手握设计模式宝典》 之 控制反转与依赖注入 (1) - 先区分好 IoC 和 DI
  • Tag: Design-PatternInversion-Of-ControlDependency-InjectionIoCDI设计模式
  • Author: Tacks
  • Create-Date: 2023-08-25
  • Update-Date: 2023-08-25

大纲

0、Series

0、REF

👩‍💻 如图所示,显然 IoC 和 DI 不是同一层面

IoC和DI和IoC-Container

1、控制反转 IoC ?

1.1 追溯历史 - 控制反转是一种设计思想,一种原理,不涉及具体模式,并通常体现在框架层

  • 👨‍🍳 概念往往都是生硬的,你来品一品

控制反转Inversion of Control ,缩写为 IoC ),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。
—> 来自维基百科

这句话只是指出面向对象中,利用控制反转可以解耦。 额…,解耦有很多种方式吧,具体怎么做,概念中没有指出来,属实是不能直观地了解。

  • 📰 1988 年的一篇论文中,《设计可重用的类》 提到 inversion of control ,但此时还并没有当成一个概念

控制反转的概念于 1988 年由 Ralph E. JohnsonBrian Foote 在他们的设计可重用类论文中首次提出,他们指出

框架的一个重要特征是,用户定义的用于定制框架的方法通常会从框架本身内部调用,而不是从用户的应用程序代码中调用。该框架通常在协调和排序应用程序活动方面发挥主程序的作用。这种控制反转使框架能够充当可扩展的骨架。用户提供的方法针对特定应用程序定制框架中定义的通用算法。

One important characteristic of a framework is that the methods defined by the user to tailor the framework will often be called from within the framework itself, rather than from the user’s application code. The framework often plays the role of the main program in coordinating and sequencing application activity. This inversion of control gives frameworks the power to serve as extensible skeletons. The methods supplied by the user tailor the generic algorithms defined in the framework for a particular application.
—> 来自《设计可重用的类》

从这段话中,能体现出来,控制反转是一种可以反转应用程序中控制流的编程原理。

例如过程式编程的时候,通常 main 函数可以利用一个 while 循环,等待用户的输入,然后根据不同的情况用 new 实例化不同的对象,调用不同的方法,直到触发结束任务。

那么有了框架以后,有了 IoC 框架以后,主流程完全由框架来做,实例化对象、调用方法,触发用户行为,从而移除 main 函数大部分责任。

类似在 PC 上的 GUI 软件,整体框架帮你做了大部分控制流程,如 while 主循环处理, 你只需要在特定按钮、特定事件等,完成任务的编写,由框架来触发调用你的任务,而不需要你调用框架的方法,由此能够感受到,执行流程发生了反转,框架起到协调应用方法执行的作用。

那是否 控制反转 通常体现在 框架中?

Wikipedia 中的解释中提到, “反转” 是相对于『过程编程』,通过控制反转,由框架调用自定义应用程序。结合现在的编程思想,也能感受在 『事件驱动编程』 中,也有控制反转,事件循环,消息调度交给事件框架处理,而你则是关注具体的事件的处理。 同样的 『Web 应用程序框架』中, 调度通常由框架的路由器来处理,而你只需要在则特定的路由器上绑定对应控制器的方法即可。(例如 Laravel 中不就是这么做的吗 ?)

  • 📑 1996 年的一篇论文中,《面向对象框架:方法论问题的调查》 中使用了 IoC 术语来区分真正的框架和类库

Michael Mattson 大佬提出的 IoC 理论。 面向对象框架和类库之间的主要区别在于框架调用应用程序代码应用程序代码调用类库。这种控制反转有时被称为好莱坞原则,“不要打电话给我们,我们打电话给你”。

The major difference between an object-oriented framework and a classlibrary is that the framework calls the application code. Normally the appli-cation code calls the class library. This inversion of control is sometimesnamed the Hollywood principle, “Do not call us, we call You
—> 来自《Object-Oriented Frameworks》

其实大致调用如下 [FrameworkMain] -> [ApplicationFunction] -> [LibraryFunction]

  • 🔧 1999 年, Apache 的 一个基金会项目 Avalon 率先使用 控制反转 IoC

Stefano Mazzocchi 将控制反转作为框架的主要驱动设计原则之一。 Apache Avalon 旨在为应用程序提供可重用的组件框架。由此也普及这一概念。
—> 来自 Apache Avalon Project

Stefano Mazzocchi 的认为 IoC 关注点在于强制隔离, 一种根据控制权将 API 与框架分开的一般原则。

1.2 概念理解 - 综上所述你如何理解 IoC

控制反转(IoC)是一种设计原则,旨在反转应用程序的控制流,以实现其类之间的松耦合。具体表现:控制反转是框架使用的一种原则,应用程序负责你处理的事情,由框架来调用你的应用方法,而不是你直接调用我。整体的控制流程发生反转。

📣 其实你已经在使用控制反转思想的产物,尽管你还没有意识到~

通常我们的开发都会用到框架,那么你首先要明白框架的使用方式,也就是你要先看文档,按照文档约束,在对应的目录下创建类编写方法。 这里也就是有一个前提,框架懂得你的代码要怎么调用,控制流程发生了反转,不再是程序员编写的程序控制整个流程,框架反转了控制流

控制反转是框架和类库的最关键性不同的部分。

📣 控制反转 是一个广泛的设计原则,是一个抽象的概念,是宏观层面的,切勿自我设限 !

1.3 如何实现 - 多种方式

  • 依赖注入模式 DI
  • 服务定位器模式 SL
  • 模板模式
  • 策略模式

2、依赖注入 DI ?

2.1 追朔历史 - DI 与 IoC 分不开的千丝万缕

依赖注入Dependency-Injection ,缩写为 DI ) 是一种设计模式,旨在分离构造对象和使用对象的关注点,从而导致松散耦合的程序。

  • 依赖:由于对象之间有了关系。比如 人依赖水,那么就产生依赖关系。(依赖类->依赖->依赖项)
  • 注入:对象的依赖项在外部已经被实例化,然后注入到内部。

例如,依赖类 A 、依赖项 B, A 依赖 B 的实例化对象。产生了依赖关系。

那么依赖注入就是 , 依赖项 B 的创建是在依赖类 A 之外完成,将依赖项 B 注入到 依赖类 A 中的过程就叫做注入,在 A 中可以直接使用 B;

反之,则需要在 A 内部实例化 依赖项 B,从而产生了耦合。

  • 🆕 2004 年, Martin Fowler 认为 控制反转 这个术语太笼统,经过讨论,决定使用 依赖注入 的名词

当这些容器谈论它们如何如此有用,因为它们实现了“控制反转”时,我最终感到非常困惑。控制反转是框架的一个共同特征,因此说这些轻量级容器是特殊的,因为它们使用控制反转,就像说我的车是特殊的,因为它有轮子一样。
—> 来自 AMartin Fowler 的博客

  • 🆚 Stefano Mazzocchi 强烈反对 Martin Fowler控制反转 重新命名为 依赖注入 的想法

Martin Fowler 将其重命名为“依赖注入”,并且在我看来,它没有抓住重点:IoC 是关于强制隔离,而不是注入依赖项。注入依赖项的需要是需要增加隔离以提高重用性的结果,它不是该模式的主要原因。
—> 来自 Stefano Mazzocchi 的博客

简单来说就是,IoC 是设计原则,关注强制隔离,现代框架大都会用到 IoC ,控制反转控制流来进行解耦。 DI 是一种设计模式,关注依赖注入项。

IoC => DI

2.2 概念理解 - 综上所述你如何理解 DI

依赖注入 (DI)是一种设计模式,其中一个对象接收它所依赖的其他对象,这些对象称为依赖项。它通过分离对象的创建和使用来实现关注点分离,从而达到 控制反转(IoC)的作用。

2.3 如何实现 - 三种方式

下面无论使用哪种注入类型,该模式都将服务的构建和配置与其使用分离,将依赖类从以前的责任中解放出来,将其与其依赖关系解耦,并提高可重用性和易于测试性。

  • 构造函数注入
    • 当通过依赖类的构造函数提供依赖项时
  • setter 注入
    • 当通过依赖类的公共属性提供依赖项时
  • 接口注入
    • 当依赖项作为参数直接提供给依赖类方法时

3、控制反转和依赖注入是同一概念吗 ?

  • 概念上:
    • 控制反转: 是一种设计原则,思想是反转应用程序的控制流,由框架来决定如何 call 你。
    • 依赖注入: 是一种设计模式,控制反转的一种实现方式,它将依赖关系定义在外部而不是内部自行实例化,分离依赖项对象的创建和使用

控制反转是一种设计思想,面向对象的一种设计原则, 而依赖注入则是一种实现这个思想的一种手段。开头的图也是能直观的体现出来。

依赖注入实现了控制反转原则,即对象获得依赖关系不再自行控制,而是反转控制权给外部。

换句话说, 通过依赖注入可以完成控制反转, 而控制反转不一定用依赖注入实现。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~