第一次遇到控制反转(或 IoC)时可能会很困惑。

  1. 它是什么?
  2. 它解决哪个问题?
  3. 什么时候适合使用,什么时候不适合使用?
有帮助吗?

解决方案

控制反转 (IoC) 和依赖注入 (DI) 模式都是为了从代码中删除依赖项。

例如,假设您的应用程序有一个文本编辑器组件,并且您想要提供拼写检查。你的标准代码看起来像这样:

public class TextEditor {

    private SpellChecker checker;

    public TextEditor() {
        this.checker = new SpellChecker();
    }
}

我们在这里所做的在 TextEditorSpellChecker。在 IoC 场景中,我们会这样做:

public class TextEditor {

    private IocSpellChecker checker;

    public TextEditor(IocSpellChecker checker) {
        this.checker = checker;
    }
}

在第一个代码示例中,我们实例化 SpellChecker (this.checker = new SpellChecker();),这意味着 TextEditor 类直接取决于 SpellChecker 班级。

在第二个代码示例中,我们通过以下方式创建一个抽象: SpellChecker 依赖类在 TextEditor 构造函数签名(不初始化类中的依赖项)。这允许我们调用依赖项,然后将其传递给 TextEditor 类,如下所示:

SpellChecker sc = new SpellChecker; // dependency
TextEditor textEditor = new TextEditor(sc);

现在客户端创建 TextEditor 类可以控制哪个 SpellChecker 要使用的实现,因为我们将依赖项注入 TextEditor 签名。

这只是一个简单的例子,有 一系列好文章 Simone Busoli 对此进行了更详细的解释。

其他提示

控制反转是程序回调时得到的结果,例如就像一个 GUI 程序。

例如,在老式菜单中,您可能有:

print "enter your name"
read name
print "enter your address"
read address
etc...
store in database

从而控制用户交互的流程。

在 GUI 程序或类似程序中,我们说:

when the user types in field a, store it in NAME
when the user types in field b, store it in ADDRESS
when the user clicks the save button, call StoreInDatabase

所以现在控制颠倒了......用户控制数据输入的顺序以及数据保存在数据库中的时间,而不是计算机按固定顺序接受用户输入。

基本上, 任何事物 事件循环、回调或执行触发器都属于这一类。

什么是控制反转?

如果您遵循以下简单的两个步骤,您就完成了控制反转:

  1. 分离 什么- 待办事项部分来自 什么时候- 待办事项部分。
  2. 确保这件事 什么时候 部分知道为 小的 尽可能关于 什么 部分;反之亦然。

根据您用于实现的技术/语言,每个步骤都可以采用多种技术。

--

反转 控制反转(IoC)的一部分是令人困惑的事情;因为 反转 是相对术语。理解 IoC 的最好方法就是忘记这个词!

--

例子

  • 事件处理。事件处理程序(做什么部分)——引发事件(何时做什么部分)
  • 接口。组件客户端(when-to-do部分)——组件接口实现(what-to-do部分)
  • xUnit 夹具。Setup 和 TearDown(做什么部分)——xUnit 框架在开始时调用 Setup,在结束时调用 TearDown(when-to-do 部分)
  • 模板方法设计模式。模板方法when-to-do部分——原始子类实现what-to-do部分
  • COM 中的 DLL 容器方法。DllMain、DllCanUnload 等(做什么部分)--COM/OS(何时做什么部分)

控制反转是关于分离关注点。

没有国际奥委会: :你有一个 笔记本电脑 电脑,你不小心打破了屏幕。该死的,你发现市场上找不到相同型号的笔记本电脑屏幕。所以你被困住了。

与国际奥委会: :你有一个 桌面 电脑,你不小心打破了屏幕。您发现您几乎可以从市场上购买任何台式显示器,并且它与您的台式机配合得很好。

在这种情况下,您的桌面成功实现了 IoC。它接受各种类型的显示器,而笔记本电脑则不接受,它需要特定的屏幕才能修复。

控制反转(或 IoC)是关于 获得自由 (你结婚了,你失去了自由,你被控制了。你离婚了,你刚刚实施了控制反转。这就是我们所说的“解耦”。好的计算机系统会阻碍一些非常亲密的关系。) 更灵活 (你办公室的厨房只提供干净的自来水,这是你想喝的唯一选择。你的老板通过安装一台新咖啡机来实施控制反转。现在您可以灵活选择自来水或咖啡。) 更少的依赖 (你的伴侣有工作,你没有工作,你在经济上依赖你的伴侣,所以你受到控制。你找到了一份工作,你就实施了控制反转。良好的计算机系统鼓励独立。)

当你使用台式电脑时,你就被奴役了(或者说被控制了)。你必须坐在屏幕前看着它。使用键盘打字并使用鼠标导航。编写糟糕的软件可能会更加奴役你。如果你用笔记本电脑取代台式机,那么你的控制权就有些倒置了。您可以轻松地拿着它并四处走动。因此,现在您可以使用计算机控制您所在的位置,而不是由计算机控制它。

通过实施控制反转,软件/对象消费者可以获得对软件/对象的更多控制/选项,而不是被控制或拥有更少的选项。

有了以上的想法。我们仍然错过了 IoC 的一个关键部分。在 IoC 场景中,软件/对象消费者是一个复杂的框架。这意味着您创建的代码不会被您自己调用。现在让我们解释一下为什么这种方式更适合 Web 应用程序。

假设您的代码是一组工作人员。他们需要建造一辆汽车。这些工人需要一个地方和工具(软件框架)来制造汽车。A 传统的 软件框架就像一个拥有许多工具的车库。所以工人们需要自己制定计划并使用工具来制造汽车。造车不是一件容易的事,工人们很难好好计划和配合。A 现代的 软件框架将像一个现代化的汽车工厂,拥有所有的设施和管理人员。工人不必制定任何计划,管理者(框架的一部分,他们是最聪明的人,制定了最复杂的计划)将帮助协调,以便工人知道何时完成他们的工作(框架调用你的代码)。工作人员只需要足够灵活,可以使用经理提供给他们的任何工具(通过使用依赖注入)。

尽管工作人员将顶层项目管理的控制权交给了管理者(框架)。但有一些专业人士的帮助是件好事。这才是IoC概念真正的由来。

具有 MVC 架构的现代 Web 应用程序依赖于框架来执行 URL 路由并将控制器放置在适当的位置以供框架调用。

依赖注入和控制反转是相关的。依赖注入位于 水平和控制反转是在 等级。你必须吃完每一口(实施 DI)才能吃完一顿饭(实施 IoC)。

在使用控制反转之前,您应该充分了解它有其优点和缺点,并且如果这样做,您应该知道为什么要使用它。

优点:

  • 您的代码被解耦,因此您可以轻松地将接口的实现与替代实现交换
  • 这是针对接口而不是实现进行编码的强大动力
  • 为代码编写单元测试非常容易,因为它只依赖于它在构造函数/设置器中接受的对象,并且您可以轻松地使用正确的对象单独初始化它们。

缺点:

  • IoC 不仅颠倒了程序中的控制流,而且还使程序变得相当复杂。这意味着您不能再仅仅读取代码并从一个位置跳转到另一个位置,因为通常位于代码中的连接不再位于代码中。相反,它位于 XML 配置文件或注释以及解释这些元数据的 IoC 容器的代码中。
  • 出现了一类新的错误,您的 XML 配置或注释错误,您可能会花费大量时间找出为什么 IoC 容器在某些条件下将空引用注入到您的一个对象中。

就我个人而言,我看到了 IoC 的优点,并且真的很喜欢它们,但我倾向于尽可能避免 IoC,因为它会将您的软件变成类的集合,这些类不再构成“真正的”程序,而只是需要由XML 配置或注释元数据如果没有它就会崩溃(并且崩溃)。

  1. 维基百科文章. 。对我来说,控制反转就是将顺序编写的代码转变为委托结构。您的程序不是显式地控制一切,而是设置一个类或库,其中包含在某些事情发生时调用的某些函数。

  2. 它解决了代码重复。例如,在过去,您需要手动编写自己的事件循环,轮询系统库以查找新事件。如今,大多数现代 API 您只需告诉系统库您感兴趣的事件,它就会让您知道它们何时发生。

  3. 控制反转是减少代码重复的实用方法,如果您发现自己复制整个方法而只更改一小部分代码,则可以考虑使用控制反转来解决它。在许多语言中,通过委托、接口甚至原始函数指针的概念可以轻松实现控制反转。

    它并不适合在所有情况下使用,因为以这种方式编写的程序流程可能更难遵循。在编写将重用的库时,这是一种设计方法的有用方法,但在您自己的程序的核心中应该谨慎使用它,除非它真正解决了代码重复问题。

但我认为你必须非常小心。如果你过度使用这种模式,你将做出非常复杂的设计,甚至更复杂的代码。

就像这个例子中的 TextEditor 一样:如果你只有一个 SpellChecker 也许真的没有必要使用 IoC ?除非你需要编写单元测试或其他东西......

反正:讲道理。设计模式有 良好做法 但不是要传讲圣经。不要把它贴得到处都是。

假设你是一个物体。然后你去了一家餐馆:

没有国际奥委会: :你要“苹果”,当你要求更多时,你总是会得到苹果。

与国际奥委会: :你可以要求“水果”。每次上菜都可以获得不同的水果。例如,苹果、橙子或西瓜。

所以,显然,当你喜欢品种时,IoC 是首选。

对我来说,IoC / DI 正在将依赖项推出到调用对象。超级简单。

非技术性的答案是能够在汽车启动之前更换发动机。如果一切都连接正确(接口),那就好了。

  1. 控制反转是一种用于解耦系统中的组件和层的模式。该模式是通过在构建组件时将依赖项注入到组件中来实现的。这些依赖关系通常作为接口提供,以进一步解耦并支持可测试性。IoC / DI 容器(例如 Castle Windsor、Unity)是可用于提供 IoC 的工具(库)。这些工具提供了超越简单依赖管理的扩展功能,包括生命周期、AOP/拦截、策略等。

  2. A。减轻组件管理其依赖项的责任。
    b.提供在不同环境中交换依赖项实现的能力。
    C。允许通过模拟依赖项来测试组件。
    d.提供一种在整个应用程序中共享资源的机制。

  3. A。在进行测试驱动开发时至关重要。如果没有 IoC,测试可能会很困难,因为被测组件与系统的其余部分高度耦合。
    b.在开发模块化系统时至关重要。模块化系统是一种无需重新编译即可更换组件的系统。
    C。如果需要解决许多跨领域的问题(尤其是在企业应用程序中),则这一点至关重要。

我把我对这两个词的简单理解写一下:

For quick understanding just read examples*

依赖注入(DI):
依赖注入一般意味着 将方法所依赖的对象作为方法的参数传递,而不是让该方法创建依赖对象.
在实践中,这意味着该方法并不直接依赖于特定的实现;任何满足要求的实现都可以作为参数传递。

通过这个对象告诉他们的依赖关系。春天使它可用。
这导致应用程序开发松散耦合。

Quick Example:EMPLOYEE OBJECT WHEN CREATED,
              IT WILL AUTOMATICALLY CREATE ADDRESS OBJECT
   (if address is defines as dependency by Employee object)

控制反转 (IoC) 容器:
这是框架,IOC的常见特征 管理java对象
– 通过 BeanFactory 从实例化到销毁。
-由IoC容器实例化的Java组件称为bean, IoC 容器管理 bean 的范围、生命周期事件和任何 AOP 功能 它已被配置和编码。

QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it.

通过实施控制反转,软件/对象消费者可以获得对软件/对象的更多控制/选项,而不是被控制或拥有更少的选项。

控制反转作为设计指南具有以下目的:

某个任务的执行与实现是解耦的。
每个模块都可以专注于其设计目的。
模块不对其他系统的行为做出任何假设,而是依赖于它们的契约。
更换模块不会对其他模块产生副作用
我将在这里保持抽象,您可以访问以下链接以详细了解该主题。
很好的例子,值得一读

详细解释

只回答第一部分。它是什么?

控制反转(IoC)意味着首先创建依赖项的实例,然后创建类的实例(可以选择通过构造函数注入它们),而不是先创建类的实例,然后类实例创建依赖项的实例。因此,控制反转 反转控制流程 的程序。 代替被调用者控制控制流程 (在创建依赖项时), 调用者控制程序的控制流程.

例如,task#1 是创建对象。如果没有 IOC 概念,task#1 应该由程序员完成。但是有了 IOC 概念,task#1 将由容器完成。

简而言之,控制从程序员反转为容器。因此,它被称为控制反转。

我发现了一个很好的例子 这里.

假设我们在某家酒店举行一些会议。

很多人,很多瓶水,很多塑料杯。

当有人想喝水时,她把杯子装满,喝完然后把杯子扔在地板上。

过了一个小时或者什么的,我们的地板上就铺满了塑料杯和水。

让反转控制。

在同一个地方举行同一次会议,但我们没有使用塑料杯,而是有一位服务员拿着一个玻璃杯(单例)

她总是主动请客人喝酒。

当有人想喝的时候,她就从服务员的杯子里拿出来喝,然后还给服务员。

撇开卫生问题不谈,最后一种饮用过程控制形式更加有效和经济。

这正是 Spring(另一个 IoC 容器,例如:吉斯)确实如此。Spring IoC 容器不是让应用程序使用 new 关键字(拿塑料杯)创建它需要的东西,而是始终向应用程序提供所需对象(一杯水)的相同实例(单例)。

将自己视为此类会议的组织者。您需要向酒店管理部门发送消息的方式

会议成员需要一杯水,但不是小菜一碟。

例子:-

public class MeetingMember {

    private GlassOfWater glassOfWater;

    ...

    public void setGlassOfWater(GlassOfWater glassOfWater){
        this.glassOfWater = glassOfWater;
    }
    //your glassOfWater object initialized and ready to use...
    //spring IoC  called setGlassOfWater method itself in order to
    //offer to meetingMember glassOfWater instance

}

有用的链接:-

我同意 空对象, ,但我想补充一点:

如果您发现自己复制了整个方法并且只更改了一小部分代码,则可以考虑通过控制反转来解决它

如果您发现自己在复制和粘贴代码,那么您几乎总是在做 某物 错误的。编码为设计原则 一次且仅一次.

似乎“IoC”这个缩写词和它所代表的名称最令人困惑的是它太迷人了——几乎是一个噪音名称。

我们真的需要一个名称来描述过程驱动编程和事件驱动编程之间的区别吗?好吧,如果我们需要的话,但是我们是否需要选择一个全新的“比生活更重要”的名字,它所带来的困惑多于它所解决的问题呢?

IoC 是关于反转你的代码和第三方代码(库/框架)之间的关系:

  • 在正常的软件开发中,您编写 主要的() 方法并调用“库”方法。 一切尽在掌控:)
  • 在 IoC 中,“框架”控制 主要的() 并调用你的方法。这 框架 一切尽在掌控:(

DI(依赖注入)是关于控制在应用程序中如何流动的。传统的桌面应用程序具有从应用程序(main() 方法)到其他库方法调用的控制流,但是随着 DI 控制流的反转,框架负责启动您的应用程序、初始化它并在需要时调用您的方法。

最后你总是赢:)

控制反转 当你去杂货店,你的妻子给你一份要购买的产品清单时。

用编程术语来说,她传递了一个回调函数 getProductList() 到您正在执行的函数 - doShopping().

它允许函数的用户定义它的某些部分,使其更加灵活。

可以在这里找到非常简单的书面解释

http://binstock.blogspot.in/2008/01/excellent-explanation-of-dependency.html

它说 -

“任何非平凡的应用程序都是由两个或多个类别的类别组成的,它们相互协作以执行某些业务逻辑。传统上,每个对象都负责获得与其(其依赖关系)合作的对象的参考。应用DI时,某些外部实体会在创建时间内给对象依赖于系统中的每个对象。换句话说,依赖关系被注入到对象中。”

控制反转是一个通用原则,而依赖注入将这一原则实现为对象图构造的设计模式(即配置控制对象如何相互引用,而不是对象本身控制如何获取对另一个对象的引用)。

将控制反转视为一种设计模式,我们需要看看我们正在反转什么。依赖注入反转了构造对象图的控制。如果用外行的话来说,控制反转意味着程序中控制流的改变。例如。在传统的独立应用程序中,我们有 main 方法,控制权从该方法传递给其他第三方库(如果我们使用了第三方库的函数),但通过控制反转,控制权从第三方库代码转移到我们的代码,因为我们正在使用第三方图书馆的服务。但程序中还有其他方面需要反转 - 例如调用方法和线程来执行代码。

对于那些对控制反转更深入感兴趣的人,已经发表了一篇论文,概述了作为设计模式的控制反转的更完整图片(OfficeFloor:使用办公模式改进软件设计 http://doi.acm.org/10.1145/2739011.2739013 并提供免费副本可供下载 http://www.officefloor.net/about.html).

确定的是以下关系:

控制反转(对于方法)=依赖(状态)注入+连续注入+线程注入

上述控制反转关系的总结可用 - http://dzone.com/articles/inversion-of-coupling-control

我找到了一个非常清楚的例子 这里 这解释了“控制是如何反转的”。

经典代码(无依赖注入)

以下是不使用 DI 的代码的大致工作方式:

  • 应用程序需要 Foo (例如控制器),所以:
  • 应用程序创建 Foo
  • 应用程序调用 Foo
    • Foo 需要 Bar (例如服务),所以:
    • Foo 创建 Bar
    • Foo 致电 Bar
      • Bar 需要 Bim(服务、存储库……),因此:
      • 酒吧创造Bim
      • 酒吧做某事

使用依赖注入

以下是使用 DI 的代码的大致工作方式:

  • 应用程序需要Foo,Foo需要Bar,Bar需要Bim,所以:
  • 应用程序创建 Bim
  • 应用程序创建 Bar 并为其提供 Bim
  • 应用程序创建 Foo 并赋予它 Bar
  • 应用程序调用 Foo
    • Foo 致电 Bar
      • 酒吧做某事

依赖关系的控制从一个被调用反转为一个调用。

它解决什么问题?

依赖注入可以轻松地与注入类的不同实现进行交换。在单元测试时,您可以注入一个虚拟实现,这使得测试变得更加容易。

前任:假设您的应用程序将用户上传的文件存储在 Google Drive 中,使用 DI 您的控制器代码可能如下所示:

class SomeController
{
    private $storage;

    function __construct(StorageServiceInterface $storage)
    {
        $this->storage = $storage;
    }

    public function myFunction () 
    {
        return $this->storage->getFile($fileName);
    }
}

class GoogleDriveService implements StorageServiceInterface
{
    public function authenticate($user) {}
    public function putFile($file) {}
    public function getFile($file) {}
}

当您的需求发生变化时,例如,您会被要求使用 Dropbox,而不是 GoogleDrive。您只需要为 StorageServiceInterface 编写一个 Dropbox 实现。只要 Dropbox 实现遵循 StorageServiceInterface,您就无需在控制器中进行任何更改。

在测试时,您可以使用虚拟实现为 StorageServiceInterface 创建模拟,其中所有方法都返回 null(或根据您的测试要求的任何预定义值)。

相反,如果您有控制器类来构造存储对象 new 像这样的关键字:

class SomeController
{
    private $storage;

    function __construct()
    {
        $this->storage = new GoogleDriveService();
    }

    public function myFunction () 
    {
        return $this->storage->getFile($fileName);
    }
}

当您想要更改 Dropbox 实现时,您必须替换其中的所有行 new GoogleDriveService 对象是构造并使用DropboxService 的。此外,在测试 SomeController 类时,构造函数始终需要 GoogleDriveService 类,并且会触发该类的实际方法。

什么时候合适,什么时候不合适?在我看来,当您认为某个类存在(或可能存在)替代实现时,您就可以使用 DI。

编程口语

IoC 简单来说:它使用 Interface 作为特定事物(例如字段或参数)的一种方式,作为可由某些类使用的通配符。它允许代码的重用。

例如,假设我们有两个类: . 。两者具有相同的品质/状态:年龄、尺寸、体重。因此,不要创建一个名为的服务类 狗服务猫服务, ,我可以创建一个名为 动物服务中心 仅当 Dog 和 Cat 使用该接口时才允许使用它们 我的动物.

然而,从务实的角度来看,它有一些倒退。

A) 大多数开发者不知道如何使用它. 。例如,我可以创建一个名为 顾客我可以自动创建 (使用IDE的工具)一个名为的接口 客户. 。因此,找到一个充满类和接口的文件夹并不罕见,无论这些接口是否会被重用。这就是所谓的臃肿。有些人可能会说“也许将来我们可以使用它”。:-|

b) 它有一些限制。举个例子,我们来谈谈这个案例 我想添加一项仅针对狗的新服务(功能)。假设我想计算训练一只狗需要多少天(trainDays()),对于猫来说没有用,猫无法被训练(我开玩笑的)。

b.1) 如果我添加 trainDays() 到服务中心 动物服务中心 那么它也适用于猫,但根本无效。

b.2) 我可以添加一个条件 trainDays() 它评估使用哪个类。但这将彻底打破IoC。

b.3) 我可以创建一个新的服务类别,称为 狗服务 只是为了新功能。但是,它将增加代码的可维护性,因为我们将有两个服务类(具有类似的功能) 这很糟糕。

我喜欢这个解释: http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/

它开始很简单,并显示了代码示例。

enter image description here

消费者 X 需要被消费的类 Y 来完成某件事。这一切都很好而且很自然,但是 X 真的需要知道它使用 Y 吗?

X 知道它使用的东西具有 Y 的行为、方法、属性等,而不知道谁实际实现了该行为,这还不够吗?

通过提取 X 在 Y 中使用的行为的抽象定义(如下图所示),并让消费者 X 使用该实例而不是 Y,它可以继续执行其操作,而无需了解 Y 的具体情况。

enter image description here

在上图中,Y 实现 I,X 使用 I 的实例。虽然 X 很可能仍然使用 Y,但有趣的是 X 并不知道这一点。它只知道它使用了实现 I 的东西。

阅读文章以获取更多信息和优势描述,例如:

  • X不再依赖于Y
  • 更灵活,可以在运行时决定实现
  • 代码单元隔离,更容易测试

...

我明白这里已经给出了答案。但我仍然认为,为了未来的读者,必须在这里详细讨论一些有关控制反转的基础知识。

控制反转 (IoC) 建立在一个非常简单的原理之上,称为 好莱坞原则. 。它说,

不要打电话给我们,我们会打电话给你

它的意思是,不要去好莱坞实现你的梦想,而是如果你值得,那么好莱坞就会找到你并让你的梦想成真。差不多颠倒了吧?

现在,当我们讨论IoC的原理时,我们常常忘记好莱坞。对于国际奥委会来说,必须有三个要素:好莱坞、你和一个像实现你的梦想这样的任务。

在我们的编程世界中, 好莱坞 代表一个通用框架(可能由您或其他人编写), 代表您编写的用户代码和 任务 代表您想要用代码完成的事情。现在你永远不会自己去触发你的任务,而不是在 IoC 中!相反,您已经设计了一切,以便您的框架将为您触发您的任务。因此,您已经构建了一个可重用的框架,可以使某人成为英雄或使另一个人成为恶棍。但这个框架总是负责的,它知道何时选择某人,而某人只知道它想成为什么。

这里将给出一个现实生活中的例子。假设您想要开发一个 Web 应用程序。因此,您创建一个框架来处理 Web 应用程序应该处理的所有常见事务,例如处理 http 请求、创建应用程序菜单、服务页面、管理 cookie、触发事件等。

然后你在框架中留下一些钩子,你可以在其中放置更多代码来生成自定义菜单、页面、cookie 或记录一些用户事件等。对于每个浏览器请求,您的框架将运行并执行您的自定义代码(如果挂钩),然后将其返回给浏览器。

所以,这个想法非常简单。您不是创建一个将控制一切的用户应用程序,而是首先创建一个可重用的框架来控制一切,然后编写自定义代码并将其连接到框架以及时执行这些代码。

Laravel 和 EJB 就是此类框架的示例。

参考:

https://martinfowler.com/bliki/InversionOfControl.html

https://en.wikipedia.org/wiki/Inversion_of_control

控制反转是将控制从库转移到客户端。当我们谈论将函数值(lambda 表达式)注入(传递)到控制(更改)库函数行为的高阶函数(库函数)的客户端时,它更有意义。将库依赖项(携带行为)注入库的客户端或框架也可以被视为 IoC

  1. 所以1号 多于. 什么是控制反转?

  2. 维护是它为我解决的第一件事。它保证我使用接口,以便两个类彼此不亲密。

使用像温莎城堡这样的集装箱,可以更好地解决维护问题。能够将访问数据库的组件替换为使用基于文件的持久性的组件,而无需更改一行代码,这真是太棒了(配置更改,您就完成了)。

一旦你进入仿制药,它会变得更好。想象一下,有一个接收记录并发布消息的消息发布者。它并不关心它发布什么,但它需要一个映射器来将记录中的内容转换为消息。

public class MessagePublisher<RECORD,MESSAGE>
{
    public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
    {
      //setup
    }
}

我写过一次,但现在如果我发布不同类型的消息,我可以将多种类型注入到这组代码中。我还可以编写映射器来获取相同类型的记录并将它们映射到不同的消息。将 DI 与泛型结合使用使我能够编写很少的代码来完成许多任务。

哦,是的,存在可测试性问题,但与 IoC/DI 的好处相比,它们是次要的。

我绝对喜欢 IoC/DI。

3.当您有一个复杂程度较高的中型项目时,它就变得更合适。我想说,当你开始感到疼痛的那一刻,它就变得合适了。

在类中创建对象称为紧耦合,Spring 通过遵循设计模式(DI/IOC)消除了这种依赖性。其中类的对象传入构造函数而不是在类中创建。此外,我们在构造函数中给出超类引用变量来定义更通用的结构。

使用 IoC,你不会更新你的对象。您的 IoC 容器将执行此操作并管理它们的生命周期。

它解决了必须手动将一种类型对象的每个实例更改为另一种类型的问题。

当您的功能将来可能会发生变化或者根据所使用的环境或配置而有所不同时,它是合适的。

为了理解这个概念,控制反转 (IoC) 或依赖反转原则 (DIP) 涉及两个活动:抽象、反转。依赖注入(DI)只是少数几种反转方法之一。

要了解更多相关信息,您可以阅读我的博客 这里

  1. 它是什么?

这是一种让实际行为来自边界之外的实践(面向对象编程中的类)。边界实体只知道它的抽象(例如,面向对象编程中的接口、抽象类、委托)。

  1. 它解决什么问题?

在编程方面,IoC试图通过模块化、解耦各个部分并使其可单元测试来解决单一代码的问题。

  1. 什么时候合适,什么时候不合适?

它在大多数情况下都是合适的,除非您只需要整体代码(例如非常简单的程序)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top