代码之家  ›  专栏  ›  技术社区  ›  andy

依赖注入是一种模式吗?是这样吗?

  •  13
  • andy  · 技术社区  · 14 年前

    IPlayerService service = Container.Resolve<IPlayerService>();
    

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

    但是,请参见下面的代码( ):

    var playerClient = new PlayerClient();
    var playerSkinClient = new PlayerSkinClient();
    IPlayerService service = new PlayerService(playerClient, playerSkinClient);
    

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

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

    2. 最后,什么定义了DI模式,如果它存在的话,没有容器的概念。

    更新

    今晚晚些时候我会更彻底地阅读答案和评论,但我只想感谢大家迄今为止深思熟虑的答案和评论!

    8 回复  |  直到 14 年前
        1
  •  3
  •   Ned Batchelder    14 年前

    在Java世界中,依赖注入通常涉及框架、容器等。但不需要那么多机器。

    在Python世界中,没有依赖注入的框架文化,因此那里的许多程序员都想知道到底是怎么回事。对他们来说,DI“只是”能够将对象或类传递给构造函数。

    回答您的具体问题:

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

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

        2
  •  15
  •   Rex M    14 年前

    martinfowler是这方面的专家,他认为依赖注入是抽象概念(称为控制反转)的具体实现的另一个名称( full article

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

    IoC也是一样,但正如Martin Fowler所说,“控制反转”是描述正在发生的事情的一种非常迟钝的方式。

    我个人并不认为“依赖注入”更好。我将其描述为“正确使用构造函数”。

    class Foo
    {
        void DoSomething()
        {
            DbConnection myConnection = new DbConnection(ConfigurationSettings...);
            myConnection.ExecuteCommand();
        }
    }
    

    使用IoC/DI也一样:

    class Foo
    {
        private DbConnection myConnection;
    
        public Foo(DbConnection conn)
        {
            myConnection = conn;
        }
    
        void DoSomething()
        {
            myConnection.ExecuteCommand();
        }
    }
    

    我恭敬地不同意那些认为它不是真正的IoC/DI的人,除非你有一个显式的binder/assembler/what把注入的类型和具体的实现连接起来,因为接收依赖项的类不知道区别。在外部类或外部配置文件中排列依赖关系是一个实现细节。

        3
  •  4
  •   Bryan Ash    14 年前

    是的,当然。

    是的,当然。

    最后,什么定义了DI模式,如果它存在的话,没有容器的概念。

    一个物体被赋予它所依赖的一切;它的依赖性被注入其中。

        4
  •  1
  •   Marc Bollinger    14 年前
    1. 是的,尽管与PicoContainer或其他非常小的容器相比,所有这些容器都经过测试并经过深思熟虑,但最终还是会实现相同的功能集。 最好的例子就是艾恩德的 "Building an IoC container in 15 lines"

    2. new ,这就是他们坚持国际奥委会理念的原因。

    3. Martin Fowler's 是规范的定义,其他地方也有很好的介绍。

        5
  •  1
  •   Community leo1    7 年前

    有趣的是,第一个例子根本不是DI,而是 Service Locator anti-pattern .

    您自己的示例是纯DI—更具体地说是 构造器注入

    DI不是一种模式,而是模式和原则的集合。当我们手工连接所有依赖项时,我们通常称之为 可怜的男人 . 换句话说,DI容器是严格可选的,但强烈建议:)

    另请参见 this description of what a DI Container brings to the table .

        7
  •  0
  •   codekaizen    14 年前

    原因是您正在安排依赖项( PlayerClient PlayerSkinClient 在您的例子中),而不是为您安排依赖项(在构造具体的 IPlayerService ). 这就是“控制反转”——你调用了构造函数,而不是调用它。这是使用DI模式的主要原因,而拥有一个容器来确定范围、解析依赖项并将其放入请求依赖项的对象中是实现这一点的具体方法。

    IPlayer服务 . 这允许您对 玩家客户端 (例如,当您要模拟它们进行构建测试时)并且不必更新初始化 IPlayer服务

        8
  •  0
  •   Will Marcouiller    14 年前

    以下是一些其他文章,可能会带来一些关于这个主题的其他重要细节,按照“应该先读”的顺序:

    1. Dependency Injection Demystified ;
    2. Dependency injection

    读完这些之后,我发现自己对这个问题有了更好的理解。