我正在开始一个新的项目,并建立了一个基础工作。一些问题已经提出,我可能会在这里问相当多的问题,希望我能找到一些答案。
第一步是处理对象的依赖关系。我决定使用依赖注入设计模式,这是我比较新的设计模式,可以为应用程序处理所有这些事情。
在实际编码时,我遇到了一个问题。如果一个类有多个依赖项,并且您希望通过构造函数传递多个依赖项(以便它们在实例化对象后无法更改)。
如何在不传递依赖数组的情况下,使用call_user_func_array()、eval()或反射?这就是我要找的:
<?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类,例如,在需要访问不同模型的控制器中?我应该静态地调用它,还是在需要它的每个类中传递它?我不认为最后一个想法是可行的。
谢谢大家。
发布于 2010-03-24 11:00:48
在开始之前,让我先说一下,我主要是一名Java程序员--只有一点PHP知识。但我将简单地尝试在没有语言细节的情况下理解最重要的概念。
依赖注入基于代码的两个部分:
在其最极端的情况下,在执行部分中没有new运算符。它们都被移到了构造部分中。(在实践中,这将被淡化。)
所有的构造都发生在构造部分。它创建自下而上执行所需的对象图。所以让我们假设,它应该构造A:
然后
首先构造
所以C不需要作为构造函数参数传递给A。这个小例子并不能很好地说明,这在多大程度上减少了需要传递的对象的数量。
依赖项注入器本身不应该被传递到执行部分。这是每个人(包括我自己)在第一次接触DI时都会犯的基本错误之一。问题是,这将完全模糊构造和执行之间的界限。另一种说法是,它会违反Law of Demeter。或者用模式的话说:它最终会将依赖注入模式“降级”为服务定位器模式。如果这真的是一种降级,这是有争议的,但在任何情况下,误用依赖项注入器作为服务定位器通常都不是一个好主意。
因此,当您需要在执行期间为一个构造的对象提供生成其他对象的能力时,您只需传递简单的提供者( Java DI框架Guice使用的术语),而不是传递依赖项注入器。这些都是相当简单的类,只能创建特定类型的对象。它们与工厂有相似之处。
首先,尝试将所需的依赖项直接传递给构造函数。
所以,总结一下:
bottom-up.
但不要走得太远:简单的对象仍然可以在没有提供程序的情况下创建:-)
现在,您所要做的就是将这些东西转换成高质量的代码。也许其他人可以通过几个PHP示例来帮助您。
附录:关于Provider的更多信息
如上所述,“提供者”这个概念(一个专门的工厂)有点特定于Java DI框架Guice。该框架可以自动为任何类型的对象创建提供程序。但是,这个概念通常对DI很有用。唯一的区别是,如果没有Guice或类似框架的帮助,您将不得不自己编写提供程序-但这非常容易:
假设B依赖于C。
get()方法编写一个名为CProvider的类,该类可以创建C的新实例。然后将CProvider的实例传递到B的构造函数中,并将该提供程序存储在B的实例字段中。现在,B可以在需要C的新实例时调用cProvider.get()。<>F244
提供程序是构造代码的一部分,因此您可以使用new C(...)!另一方面,它们不是执行代码的一部分,所以您不应该在那里有任何执行逻辑。
当然,CProvider可以传递给多个构造函数。您还可以编写多个版本的CProvider1、CProvider2等,其中每个版本都可以构造具有不同属性的不同版本的C对象。或者,您可以使用不同的参数多次实例化CProvider。
发布于 2010-03-24 10:33:11
您应该考虑使用IOC容器来管理您的依赖项。一个好的IOC容器应该负责在依赖的构造器之间传递依赖关系。
有一个现有的question询问有关PHP的IOC容器选项。
发布于 2010-03-24 10:34:27
看起来你正在尝试使用你自己的依赖注入容器。为什么不使用已经存在的,如Symfony、Crafty或Sphicy
https://stackoverflow.com/questions/2504798
复制相似问题