Php 依赖项注入防止依赖项容器上的依赖项
在对依赖注入感到困惑之后,我担心依赖DI容器。所以我想我把一切都和工厂联系在一起。但似乎需要大量的工厂(每个对象一个(?) 现在发生的情况如下:Php 依赖项注入防止依赖项容器上的依赖项,php,oop,design-patterns,dependency-injection,Php,Oop,Design Patterns,Dependency Injection,在对依赖注入感到困惑之后,我担心依赖DI容器。所以我想我把一切都和工厂联系在一起。但似乎需要大量的工厂(每个对象一个(?) 现在发生的情况如下: class houseFactory { protected $_di; public function __construct(\DI $di) { $this->_setDI($di) } protected function _setDI(\DI $di) {
class houseFactory
{
protected $_di;
public function __construct(\DI $di)
{
$this->_setDI($di)
}
protected function _setDI(\DI $di)
{
$this->_di = $di;
}
public function createObject()
{
return $this->_di->create('house');
}
}
houseFactory基本上将创建和调用代码连接在一起,而不必知道如何创建房屋。但实际上,为每一个需要的对象建立一个新工厂真的可以吗
现在看来是这样,因为假设house单靠DI容器并不是那么容易解决的问题,但需要一定的规则。例如,应该只有一个实例(也称为“共享”)。这些规定将被纳入工厂
我的问题是:
1) 这可以接受吗
我预测会有大量的工厂,我担心这将是一个过度的/巨大的缺点/与它应该做的相反
2) 什么时候使用“new”关键字才算“ok”
我理解为什么移动逻辑来创建一个具有依赖关系的新对象是一个好的实践。但它似乎是循环的
3) 依赖项注入容器在应用程序中的位置和方式
您实际上从什么角度使用/调用DI容器?看起来像是将DI容器硬编码到应用程序中?或者这就是重点
希望我的问题不会含糊不清
提前感谢。DI的主要目的是注入依赖项,而不是注入负责解析/创建对象的对象。在您的示例中,假设我们希望使用
houseFactory
类来获取house
类并使用它(例如goHome方法)
该实现不仅使调用方依赖于house
类,而且还依赖于houseFactory
类,这是一种无用的依赖
正如TrueWill所说,应用程序负责创建对象的唯一地方是合成根。compositionroot
是每个应用程序的起点。不幸的是,我不认为在纯php类中有任何组合根,但是在php框架(如CI或Zend)中应该有
为什么要在合成根目录中创建对象
使对象创建的范围变得非常小。组合根目录通常只包含启动应用程序的小逻辑。可能是处理一般异常的其他逻辑,但不是其他逻辑。因此,创建对象是安全的,因为不存在特定的业务逻辑
未在其他类中创建合成根。它被称为应用程序启动,因此在类中创建对象是安全的
要了解更多有关CompositionRoot的信息,您可以阅读MarkSeeman的书或他的博客
那么我们如何访问在CompositionRoot中创建的对象呢
有些应用程序对DI有很好的支持,例如ASP.NETMVC,但是有些应用程序不喜欢ASP.NETWebForm。在具有良好支持的应用程序中,您可以直接从组合根
注入类。然而,如果不是这样,也许您可以通过静态类访问组合根DI容器,但只能在页面的构造函数中访问。因此,它最小化了对合成根的访问
编辑1:
下面是没有用php编写DI容器的house类的使用示例(可能不起作用,没有在php中使用DI)
这是C#console中的示例:
这个实现仍然是安全的,因为DIContainer只在页面的构造函数级别使用。但是确保不要在服务类中执行此操作。例如:
public class Renter : IRenter{
public Renter(){
this.house = CompositionRoot.DiContainer.Create("house");
}
private IHouse house;
}
这是个糟糕的设计。Renter类依赖于DIContainer。要解决这个问题,请注入IHouse
类
public class Renter : IRenter{
public Renter(IHouse house){
this.house = house;
}
private IHouse house;
}
那么Renter类的调用方应该通过house类。示例是使用poor-man将iInter类分配给DIContainer
Dictionary<Type, object> DiContainer = new Dictionary<Type, object>();
IHouse house = new House();
IRenter renter = new Renter(house);
DiContainer.Add(typeof(IHouse), house);
DiContainer.Add(typeof(IRenter), renter);
请参阅-应用程序中只有一个地方(通常)应该知道有关DI容器的任何信息。如果我理解正确,它只会告诉我在哪里创建DI容器本身?但不是在哪里建立工厂等?你可能不需要任何工厂。正如Mark Seemann所说,您可以在根中组成整个对象图。我建议你阅读他的博客文章(或者更好的是,买他的)——他比我更善于解释。你能举一个例子说明你文章中的$house例子应该是怎样的吗?(带电话号码)提前谢谢!你能澄清一下的含义吗?实际上应该是?谢谢。我想我还有一个问题。DI容器是否在“main”方法之外实际使用?如何在“main”方法之外创建新对象?让我们说我是几个深沉的物体。我如何在那里创建房子?更新了我的答案,但在C#中,我并不是一个真正的静力学爱好者。它隐藏了任何事物的真正依赖性。为什么在构造函数级别使用DI容器?谢谢你的帮助,顺便说一句:)!
public class Page1 : Page{
public Page1(){
this.house = CompositionRoot.DiContainer.Create("house");
}
private IHouse house;
}
public class Renter : IRenter{
public Renter(){
this.house = CompositionRoot.DiContainer.Create("house");
}
private IHouse house;
}
public class Renter : IRenter{
public Renter(IHouse house){
this.house = house;
}
private IHouse house;
}
Dictionary<Type, object> DiContainer = new Dictionary<Type, object>();
IHouse house = new House();
IRenter renter = new Renter(house);
DiContainer.Add(typeof(IHouse), house);
DiContainer.Add(typeof(IRenter), renter);
public class Page1 : Page{
public Page1(){
this.renter = (IRenter)CompositionRoot.DiContainer[typeof(IRenter)];
}
private IRenter renter;
}