3

我已经阅读了几天关于依赖注入/控制反转的内容,并且正在努力理解一个概念。

假设我有以下简单的场景:

public interface ILocation
{
    string LocationName { get; set; }
}

// The implementation / concrete class for ILocation
public class Location : ILocation
{
    public string LocationName {
        get { /* logic */ }
        set { /* logic */ }
    }
}


// My class that depends on ILocation as a dependency
public class SomeClass{
    public SomeClass(ILocation location)
    {
        this.theLocation = location;
    }

    // 
    // more code...
    // 
}

太好了,所以我将我的ILocation注入到我的SomeClass......但我必须在我的依赖注入框架ILocation中处理并编译它。Location(旁白:我意识到有些框架可以在文件中进行此配置,即 XML 配置文件)

当上面列出的所有组件都必须在编译时存在时,创建这种知识“分离”的意义何在?

这真是折磨我。也许我完全错过了重点。现在,话虽这么说,我确实看到很多人谈论“可测试性”,我可以看到那里的优势,但是让我们假设我们将测试抛到了窗外;还有什么优点?这真的给了我什么?

我最初寻找这个概念是为了了解更多信息,希望能找到一种为我正在构建的应用程序设计“插件”模式的好方法。到目前为止,这似乎不适用于运行时插件的概念。

期待有关该主题的见解-谢谢!

4

4 回答 4

3

让我们上你的课,摆脱 DI。

public class SomeClass
{
    private Location _location = new Location();
    public SomeClass()
    {
    }
}

太好了,您可以创建 Location 对象,并且它的构造函数中不接受任何参数。代码看起来很漂亮,而且很容易对吧?但是等等,现在 Location 类发生了变化,需要它自己的依赖项 LocationFinder。所以我们将它添加到对象构造中,也许我们将它移到构造函数中。

public class SomeClass
{
    private Location _location;
    public SomeClass()
    {
         _location = new Location(new LocationFinder());
    }
}

好吧,不那么漂亮,但还不算太糟糕。但果然 6 个月后 LocationFinder 必须改变,现在它需要从一个工厂 LocationFinderFactory 中创建,它有自己的依赖项。

public class SomeClass
{
    private Location _location;
    public SomeClass()
    {
        var locationFinderFactory = new LocationFinderFactory(new LocationFinderStrategy());
        _location = new Location(locationFinderFactory.Create());
    }
}

不是很干净,不是吗?更值得注意的一点是,每次 Location 实现更改时,您也必须更改 SomeClass。 您已经将 SomeClass 的实现耦合到 Location 和其他 3 个类! 现在,每次这 4 个类中的任何一个必须更改时,您都将更改 SomeClass。

故事的道德,以松散耦合的方式(例如使用 DI)对您的类进行编码,并且这些类型的代码更改将仅本地化到它应该影响的类。

于 2013-03-21T22:12:57.803 回答
2

依赖注入的第一个目标是使代码易于单元测试。

然后是额外的优势,比如可以注入代理(AOP,用于事务、安全检查等)、配置注入的组件、根据配置文件或配置选择实现等。所有这些都取决于你的框架。

于 2013-03-21T21:52:53.027 回答
1

你得到的是关注点分离。使用 DI,您可以自由更改实现或换出实现,ILogger 而无需修改(甚至重新编译)SomeClass。使用 DI,SomeClass并不关心实现接口的类是什么ILogger,只要它实现了接口中的所有方法即可。如果你使用具体的类,如果你想改变哪个类实现了这些方法,你也必须修改SomeClass。使用 DI,您只需更改将发送到构造函数的类或 IoC 容器的配置,而无需修改SomeClass自身。

于 2013-03-21T21:55:34.543 回答
0

管理系统内部依赖项的方式对软件的质量(灵活性、健壮性、可重用性、可维护性)产生巨大影响,尤其是从长远来看,当您的系统随着时间的推移而发生大量变化时。依赖注入是管理依赖的一种强大工具(除其他外)。

这篇文章很好地讨论了这个话题,所以我不会尝试复制它:) http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf

于 2013-03-21T22:04:27.960 回答