首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >访问DI容器

访问DI容器
EN

Stack Overflow用户
提问于 2010-03-24 09:31:02
回答 3查看 2K关注 0票数 10

我正在开始一个新的项目,并建立了一个基础工作。一些问题已经提出,我可能会在这里问相当多的问题,希望我能找到一些答案。

第一步是处理对象的依赖关系。我决定使用依赖注入设计模式,这是我比较新的设计模式,可以为应用程序处理所有这些事情。

在实际编码时,我遇到了一个问题。如果一个类有多个依赖项,并且您希望通过构造函数传递多个依赖项(以便它们在实例化对象后无法更改)。

如何在不传递依赖数组的情况下,使用call_user_func_array()、eval()或反射?这就是我要找的:

代码语言:javascript
复制
<?php

class DI
{
    public function getClass($classname)
    {
        if(!$this->pool[$classname]) {
            # Load dependencies
            $deps = $this->loadDependencies($classname);

            # Here is where the magic should happen
            $instance = new $classname($dep1, $dep2, $dep3);

            # Add to pool
            $this->pool[$classname] = $instance;

            return $instance;
        } else {
                return $this->pool[$classname];
        }
    }
}

再一次,我希望避免使用最昂贵的方法来调用这个类。还有其他建议吗?

另外,我如何访问类中的DI类,例如,在需要访问不同模型的控制器中?我应该静态地调用它,还是在需要它的每个类中传递它?我不认为最后一个想法是可行的。

谢谢大家。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-03-24 11:00:48

在开始之前,让我先说一下,我主要是一名Java程序员--只有一点PHP知识。但我将简单地尝试在没有语言细节的情况下理解最重要的概念。

依赖注入基于代码的两个部分:

  1. Construction
  2. Execution

在其最极端的情况下,在执行部分中没有new运算符。它们都被移到了构造部分中。(在实践中,这将被淡化。)

所有的构造都发生在构造部分。它创建自下而上执行所需的对象图。所以让我们假设,它应该构造A:

  • A依赖于B,
  • B依赖于C。

然后

首先构造

  • C,然后以C作为parameter.
  • Then构造B,以B为参数构造A。

所以C不需要作为构造函数参数传递给A。这个小例子并不能很好地说明,这在多大程度上减少了需要传递的对象的数量。

依赖项注入器本身不应该被传递到执行部分。这是每个人(包括我自己)在第一次接触DI时都会犯的基本错误之一。问题是,这将完全模糊构造和执行之间的界限。另一种说法是,它会违反Law of Demeter。或者用模式的话说:它最终会将依赖注入模式“降级”为服务定位器模式。如果这真的是一种降级,这是有争议的,但在任何情况下,误用依赖项注入器作为服务定位器通常都不是一个好主意。

因此,当您需要在执行期间为一个构造的对象提供生成其他对象的能力时,您只需传递简单的提供者( Java DI框架Guice使用的术语),而不是传递依赖项注入器。这些都是相当简单的类,只能创建特定类型的对象。它们与工厂有相似之处。

首先,尝试将所需的依赖项直接传递给构造函数。

所以,总结一下:

bottom-up.

  • Only传递创建对象所需的尽可能少的依赖项。

  • 完成后,启动bottom-up.

  • Only执行,您仍然可以使用提供程序获取新创建的对象。

但不要走得太远:简单的对象仍然可以在没有提供程序的情况下创建:-)

现在,您所要做的就是将这些东西转换成高质量的代码。也许其他人可以通过几个PHP示例来帮助您。

附录:关于Provider的更多信息

如上所述,“提供者”这个概念(一个专门的工厂)有点特定于Java DI框架Guice。该框架可以自动为任何类型的对象创建提供程序。但是,这个概念通常对DI很有用。唯一的区别是,如果没有Guice或类似框架的帮助,您将不得不自己编写提供程序-但这非常容易:

假设B依赖于C。

  • 如果B只需要C的一个固定实例,则不需要提供程序-您可以简单地使用构造函数参数C构造B。
  • 如果B在执行过程中需要创建更多的C实例,则只需使用get()方法编写一个名为CProvider的类,该类可以创建C的新实例。然后将CProvider的实例传递到B的构造函数中,并将该提供程序存储在B的实例字段中。现在,B可以在需要C的新实例时调用cProvider.get()。<

>F244

提供程序是构造代码的一部分,因此您可以使用new C(...)!另一方面,它们不是执行代码的一部分,所以您不应该在那里有任何执行逻辑。

当然,CProvider可以传递给多个构造函数。您还可以编写多个版本的CProvider1CProvider2等,其中每个版本都可以构造具有不同属性的不同版本的C对象。或者,您可以使用不同的参数多次实例化CProvider

票数 23
EN

Stack Overflow用户

发布于 2010-03-24 10:33:11

您应该考虑使用IOC容器来管理您的依赖项。一个好的IOC容器应该负责在依赖的构造器之间传递依赖关系。

有一个现有的question询问有关PHP的IOC容器选项。

票数 2
EN

Stack Overflow用户

发布于 2010-03-24 10:34:27

看起来你正在尝试使用你自己的依赖注入容器。为什么不使用已经存在的,如SymfonyCraftySphicy

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

https://stackoverflow.com/questions/2504798

复制
相关文章

相似问题

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