依赖注入是一种模式,是吗?

and*_*ndy 13 design-patterns dependency-injection inversion-of-control

我和我的一位同事就依赖注射问题进行了激烈的辩论,并意识到我并不完全了解这个主题的所有事实.

所以,拿这个代码(就是你知道,我们正在使用Castle Windsor)

IPlayerService service = Container.Resolve<IPlayerService>();
Run Code Online (Sandbox Code Playgroud)

上面的代码显然是使用IoC的DI的一个例子.

但是,请参阅下面的代码(更新:假设我通过构造函数传递所有外部依赖项):

var playerClient = new PlayerClient();
var playerSkinClient = new PlayerSkinClient();
IPlayerService service = new PlayerService(playerClient, playerSkinClient);
Run Code Online (Sandbox Code Playgroud)

我的论点是上面的代码是DI模式的一个例子,DI可以在没有IoC的情况下存在.

现在,我的同事并没有完全不同意我的观点,但他说上面的代码不是涉及DI的任何模式的例子.

  1. 那么,DI可以仅用作一种模式而不需要任何额外的框架吗?

  2. 如果是这样,上面的代码是一个例子吗?

  3. 最后,定义DI模式(如果存在),没有Container的概念.

UPDATE

我今晚稍后会更详细地回答和评论,但感谢大家对目前为止经过深思熟虑的答案和评论!

Rex*_*x M 15

根据Martin Fowler的说法,他是这个主题的专家,依赖注入是抽象概念的具体实现的另一个名称,称为控制反转(全文).

从根本上说,所有DI的意思是:一个类依赖于正确工作的对象被初始化并在外部传递给它,而不是类本身负责获取/初始化这些对象.如何实现这一点的具体细节超出了模式的范围.

IoC是一回事,但正如Martin Fowler所说,"控制倒置"是描述正在发生的事情的一种非常迟钝的方式.

我个人认为"依赖注入"并不是更好.我会将其描述为"正确使用构造函数".

非IoC /非DI的示例:

class Foo
{
    void DoSomething()
    {
        DbConnection myConnection = new DbConnection(ConfigurationSettings...);
        myConnection.ExecuteCommand();
    }
}
Run Code Online (Sandbox Code Playgroud)

使用IoC/DI也是如此:

class Foo
{
    private DbConnection myConnection;

    public Foo(DbConnection conn)
    {
        myConnection = conn;
    }

    void DoSomething()
    {
        myConnection.ExecuteCommand();
    }
}
Run Code Online (Sandbox Code Playgroud)

我恭敬地不同意那些认为它不是真正的IoC/DI的人,除非你有一个明确的binder /汇编程序/你有什么把连接注入的类型和具体的实现连接起来,因为接收依赖的类不知道区别.是否在外部类或外部配置文件中安排依赖项是实现细节.


Ned*_*der 3

在Java世界中,依赖注入常常涉及到框架、容器等。但不需要所有这些机器。

依赖注入的本质是一个类能够被分配它所依赖的对象,而不是在实现中对它们进行硬编码。如果您可以从类外部“注入”这些“依赖项”,那么您就拥有依赖项注入。框架可能是实现此目的的好方法,但这不是必需的。

在 Python 世界中,不存在依赖注入的框架文化,因此许多程序员想知道这有什么大惊小怪的。对他们来说,DI“只是”能够将对象或类传递到构造函数中。

回答您的具体问题:

  1. 是的,DI 可以在没有框架的情况下完成。

  2. 是的,上面的代码就是一个例子:PlayerService 不知道 PlayerClient 或 PlayerSkinClient 来自哪里。他们已被注入课堂。请注意,这里的其他人已经回答了“否”。

  3. 往上看。