【问题标题】:How to avoid injecting dependencies into an object so that it can pass them on?如何避免将依赖项注入对象以便它可以传递它们?
【发布时间】:2010-04-07 10:36:52
【问题描述】:

我有兴趣将依赖注入应用到我当前的项目中,它使用了 MVC 模式。

我的控制器将调用模型,因此需要将依赖项注入模型。为此,控制器必须首先具有依赖项(例如数据库对象)。控制器不需要使用其中的一些依赖(比如数据库对象),所以我觉得不应该给它这个依赖。但是,如果要将它们注入模型对象,则必须具有这些依赖关系。

如何避免将依赖项注入到对象中以便它可以传递它们?这样做感觉不对,可能会导致许多依赖项被注入到一个对象中。

编辑:我正在使用 PHP。

【问题讨论】:

    标签: model-view-controller design-patterns architecture dependency-injection


    【解决方案1】:

    我同意您的担忧。仅出于将依赖项传递给其他依赖项的目的而获取依赖项是一种代码味道。

    根据这些依赖项之间的确切交互,您有几个选择:

    如果只需要一个依赖实例

    如果您的 Controller 只需要一个依赖项的实例,那么只需对其进行依赖即可。

    (为c#代码道歉)

    不要这样做:

    public class MyController
    {
        public MyController(IDb db)
        {
            var dep = new MyDependency(db);
            // Use dep or save it for later
        }
    }
    

    相反,您可以这样做:

    public class MyController
    {
        public MyController(MyDependency dep)
        {
            // Use dep or save it for later
        }
    }
    

    您可能需要考虑接口本身背后的MyDependency。另见Refactoring to Aggregate Services。

    如果您需要在 Controller 的生命周期内创建多个实例

    但是,有时您需要动态创建多个实例。当您需要一个仅在运行时可用的值才能完全填充依赖项时,通常会出现这种情况。

    在这种情况下,Abstract Factory 是 excellent and universal solution。

    【讨论】:

    • 我不完全理解您建议我应该如何处理您的第一个选项。您是否将依赖项捆绑在一起并将它们作为一个传递?
    • 这是一种选择。然而,要点是消费者根本不应该创建依赖项,而是通过将其作为构造函数参数来请求它。
    • 将依赖项捆绑在一起并将它们传递给控制器​​与单独传递它们几乎相同吗?这是一种不同的方法,但您仍然将依赖项传递给它不使用的控制器。我想我可能误解了你的意思!
    • 控制器不必向 DAL 提供数据库对象,因为控制器不会“新建” DAL。控制器向 DAL 请求 IoC 容器(或您创建的执行相同功能的对象),而 IoC 容器负责向 DAL 提供数据库对象。
    • @Pheter:这当然是一种方法。当您的 Controller 需要多个 DAL 实例时,或者如果它需要收集 DAL 的选择所依赖的运行时值时,注入的抽象工厂是有意义的。否则,您还不如直接注入 DAL。无论如何,如果没有代码,很难说您尝试做的事情是否正确。我是否可以建议您编辑您的问题以包含一些代码,或者用代码提出一个新问题?
    【解决方案2】:

    我不是根据 PHP 经验说话,但您应该查看 Inversion of Control (IOC) Containers。

    StackOverflow 上的 question 讨论了用于 PHP 的 IOC 容器。要快速了解一些other benefits of IOC Containers,您应该查看这个问题,这可能是我在网站上最喜欢的问题之一。检查最后一个答案;)

    如何避免依赖 注入到一个对象中,这样 它可以传递它们吗?这样做感觉 错误并可能导致许多 依赖项被注入到 对象。

    大多数人没有意识到 IOC 容器使存储临时依赖项的需求无效。这反过来又使您的代码更清晰,更易于遵循。代码的每个类(或模块)只是询问它需要什么。 IOC Containers 可以管理对象的生命周期,因此即使两个类独立请求相同的依赖项,它们也可以接收相同的实例,这非常简洁。

    【讨论】:

      猜你喜欢
      • 2015-06-21
      • 2011-07-09
      • 2022-12-13
      • 2015-07-07
      • 2020-04-06
      • 1970-01-01
      • 1970-01-01
      • 2021-04-20
      • 1970-01-01
      相关资源
      最近更新 更多