And*_*dre 10 php dependency-injection
我正在开始一个新项目并建立基础来开展工作.一些问题已经上升,我可能会在这里问一些问题,希望我会找到一些答案.
第一步是处理对象的依赖关系.我已经决定使用依赖注入设计模式,我有点新,为应用程序处理所有这些.
实际编码时,我遇到了一个问题.如果一个类有多个依赖项,并且您希望通过构造函数传递多个依赖项(以便在实例化对象后无法更改它们).
如何在不传递依赖数组的情况下使用call_user_func_array(),eval()或Reflection?这就是我要找的:
<?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];
}
}
}
Run Code Online (Sandbox Code Playgroud)
同样,我想避免使用最昂贵的方法来调用该类.还有其他建议吗?
另外,如何在类中访问DI类,例如,在需要访问不同模型的控制器中?我应该静态地调用它还是将它传递给需要它的每个类?我不认为最后的想法是可行的.
感谢大家.
Chr*_*her 23
[在开始之前,让我说我主要是一个Java程序员 - 只有一点点PHP知识.但我会简单地尝试在没有语言细节的情况下获得最重要的概念.
依赖注入基于两部分代码:
在最极端的形状中,new执行部分中没有找到操作符.所有这些都被移到了构造部分.(在实践中,这将会降低.)
所有施工都在 - 施工部分.它创建了自下而上执行所需对象的图形.所以我们假设,它应该构造一个A:
然后
所以C不必作为构造函数参数传递给A.这个小例子没有足够强烈地说明,这减少了多少必须传递到极小数量的对象的数量.
不应将依赖注入器本身传递到执行部分.当他们第一次接触DI时,这是每个人(包括我自己)试图犯下的基本错误之一.问题是,这将完全模糊构造和执行之间的界限.另一种说法是,它违反了得墨忒耳法则.或者在模式中说:它最终会将依赖注入模式"降级"为服务定位器模式.这是有争议的,如果这确实是一种退化,但无论如何,滥用依赖注入者作为服务定位器通常不是一个好主意.
因此,每当您需要为构造对象之一提供在执行期间生成其他对象的能力时,您只需传递简单的Providers(Java DI框架Guice使用的术语),而不是传递Dependency Injector .这些是相当简单的类,只能创建某种对象.他们与工厂有相似之处.
首先尝试将所需的依赖项直接传递给构造函数.
所以,总结一下:
但是不要太过分:在没有提供者的情况下仍然可以创建简单的对象:-)
现在,您所要做的就是将这些内容翻译成高质量的代码.也许其他人可以通过一些PHP示例帮助您.
附录:关于提供商的更多信息
如上所述,概念"Provider"(专用工厂)对Java DI框架Guice有点特殊.此框架可以自动为任何类型的对象创建提供程序.但是,这个概念通常对DI有用.唯一的区别是,没有Guice或类似框架的帮助,你必须自己编写提供者 - 但这很容易:
比方说,B取决于C.
CProvider用get()方法调用的类,即可以创建C的新实例.然后将实例传递给CProviderB的构造函数,并将Provider存储在实例字段中B.现在B可以cProvider.get()在需要新的C实例时调用.提供商是构造代码的一部分,因此您可以使用new C(...)!另一方面,它们不是执行代码的一部分,所以你不应该有任何执行逻辑.
CProvider当然可以传递给多个构造函数.您还可以编写多个版本CProvider1,CProvider2... - 其中每个版本都可以构造具有不同属性的不同版本的C对象.或者您CProvider使用不同的参数简单地实例化多次.