首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解依赖注入

理解依赖注入
EN

Software Engineering用户
提问于 2014-03-13 09:26:02
回答 6查看 20.7K关注 0票数 121

我正在阅读关于依赖注入 (DI)的文章。对我来说,这是一件非常复杂的事情,因为我读到它也提到了倒置控制 (IoC),所以我觉得我要去旅行了。

这就是我的理解:不是在类中创建模型,而是将模型(已经填充了有趣的属性)传递(注入)到需要它的地方(传递给一个新类,它可以将它作为构造函数中的一个参数)。

对我来说,这只是在传递一个论点。我一定是没听懂重点吧?也许更大的项目会变得更明显?

我的理解是非DI(使用伪代码):

代码语言:javascript
复制
public void Start()
{
    MyClass class = new MyClass();
}

...

public MyClass()
{
    this.MyInterface = new MyInterface(); 
}

而DI将会是

代码语言:javascript
复制
public void Start()
{
    MyInterface myInterface = new MyInterface();
    MyClass class = new MyClass(myInterface);
}

...

public MyClass(MyInterface myInterface)
{
    this.MyInterface = myInterface; 
}

有人能给我一点启发吗?我肯定我在这里搞得一团糟。

EN

回答 6

Software Engineering用户

回答已采纳

发布于 2014-03-13 09:44:32

是的,您可以通过构造函数或属性注入依赖项。

造成这种情况的原因之一是,不要在MyClass中包含如何构造MyInterface实例的详细信息。MyInterface本身可能有一个完整的依赖列表,如果您在MyClass中实例化了所有的MyInterface依赖项,那么MyClass的代码会很快变得丑陋。

另一个原因是测试。

如果您依赖于文件读取器接口,并且通过构造函数(例如ConsumerClass)注入该依赖项,这意味着在测试期间,您可以将文件读取器的内存中实现传递给ConsumerClass,从而避免在测试期间执行I/O操作。

票数 112
EN

Software Engineering用户

发布于 2014-03-13 13:38:30

我们的朋友在堆栈溢出有一个对此的回答很好。我最喜欢的是第二个答案,包括以下一句话:

“依赖注入”是一个5美分概念的25美元术语。(...)依赖注入意味着向对象提供其实例变量。(.)

来自詹姆斯·肖尔的博客。当然,在此基础上还有更复杂的版本/模式,但这足以从根本上理解正在发生的事情。不是创建自己的实例变量的对象,而是从外部传入它们。

票数 49
EN

Software Engineering用户

发布于 2014-03-13 22:22:53

假设你正在你的客厅做室内设计:你在天花板上安装了一盏漂亮的吊灯,插上一盏与之匹配的古典落地灯。一年后,你可爱的妻子决定她想要的房间不那么正式。哪种照明装置会更容易更换?

DI背后的想法是在任何地方使用“插件”方法。如果你住在一个简陋的小木屋里,没有干墙,而且电线都暴露了出来,这看起来就没什么大不了的了。(你是个勤杂工--你可以改变任何事情!)同样,在一个小而简单的应用程序上,DI可以增加比它更多的复杂性。

但是对于一个庞大而复杂的应用来说,DI对于长期的维护是必不可少的.它允许您从代码中“拔出”整个模块(例如,数据库后端),并将它们与不同的模块进行交换,这些模块可以完成相同的任务,但以完全不同的方式(例如云存储系统)完成。

顺便说一下,如果没有.NET中的依赖注入的推荐,对DI的讨论将是不完整的,由Mark提出。如果您熟悉.NET,并且您曾经打算参与大规模的SW开发,这是一个基本的阅读。他比我更好地解释了这个概念。

让我给您留下DI的最后一个基本特性,您的代码示例忽略了这一点。DI允许您利用封装在谚语“程序到接口”中的巨大的灵活性潜力。若要稍微修改示例,请执行以下操作:

代码语言:javascript
复制
public void Main()
{
    ILightFixture fixture = new ClassyChandelier();
    MyRoom room = new MyRoom (fixture);
}
...
public MyRoom(ILightFixture fixture)
{
    this.MyLightFixture = fixture ; 
}

但是现在,由于MyRoom是为ILightFixture接口设计的,所以我可以在明年轻松地进入主函数的一行(“注入”另一个“依赖项”),然后我立即在MyRoom中获得新的功能(如果它恰好位于一个单独的库中,则无需重新构建或重新部署MyRoom。当然,这假定您的所有ILightFixture实现的设计都考虑了Liskov替换)。总之,只要做一个简单的改变:

代码语言:javascript
复制
public void Main()
{
    ILightFixture fixture = new MuchLessFormalLightFixture();
    MyRoom room = new MyRoom (fixture);
}

此外,我现在可以单元测试MyRoom (您是单元测试,对吗?)并使用“模拟”灯具,它允许我测试完全独立于MyRoomClassyChandelier.

当然,还有更多的优势,但这些都是卖给我的。

票数 19
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/232229

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档