依赖注入防止依赖容器的依赖
在依赖注入困惑之后,我担心依赖于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基本上将创建和调用代码连接在一起,而不必知道如何创建房屋。 但是真的需要为每个需要的对象召集一个新的工厂吗?
现在看起来如此,因为我们可以说房子不是很容易通过DI容器解决,但需要一定的规则。 例如,应该只有一个实例(也称为“共享”)。 这些规则将进入工厂。
我的问题是:
1)这可以接受吗?
我预测一大批工厂,我担心的是这将是一个矫枉过正/巨大的缺点/对付它应该做的事情。
2)什么时候使用'new'关键字实际上是'ok'?
我明白为什么移动逻辑来创建一个具有依赖关系的新对象是很好的做法。 但似乎是通告。
3)依赖注入容器在哪里以及如何在应用程序中发挥作用?
您实际使用/调用DI容器的哪一点? 好像将DI容器硬编码到您的应用程序中? 或者这实际上是重点?
希望我的问题不要模糊。
提前致谢。
DI的主要目的是注入依赖项,而不是注入负责解析/创建对象的对象。 在你的例子中,假设我们想使用houseFactory
类来获得house
类并使用它(例如goHome方法)。
$house = $houseFactory->createObject();
$house->goHome();
这个实现不仅使你的调用者依赖于house
类,而且还依赖于houseFactory
类,这是一种无用的依赖。
正如TrueWill所说,负责创建对象的应用程序唯一的地方就是composition root
。 composition root
是每个应用程序的起点。 不幸的是我不认为在纯php类中有任何组合根,但是应该在php框架中使用,例如CI或Zend。
我们为什么要在composition root
创建对象?
要了解更多关于作文根的信息,你可以在Mark Seeman的书或他的博客上阅读。
那么我们如何访问在组合根中创建的对象?
一些应用程序对DI有很好的支持,比如ASP.Net MVC,但有些不像ASP.Net Webform。 在具有良好支持的应用程序中,您可以直接从composition root
注入该类。 但是,如果没有,也许你可以通过静态类访问组合根DI容器,但只能在页面的构造函数中访问。 所以它最大限度地减少了组合根的访问。
EDIT1:
这里是没有用PHP写的DI容器的房子类的使用示例(可能不工作,在php中没有使用DI)。
class houseConsumer{
protected $_house;
public function __construct(DI $house)
{
$this->_house($house)
}
public function doSomething(){
// do something
$this->_house->goHome();
}
}
class compositionRoot{
public function main(){
$diContainer = // define the DI Container
$houseConsumer = new houseConsumer($diContainer->create('house'));
$houseConsumer->doSomething();
}
}
这是C#控制台中的示例:
public class HouseConsumer{
//constructor
public HouseConsumer(IHouse house){
this.house = house;
}
IHouse house;
public void DoSomething(){
house.GoHome();
}
}
//this is the composition root
public class Program{
public static void Main(string[] args){
List<object> diContainer = new List<object>();
//populate diComponent
HouseConsumer consumer = new HouseConsumer((IHouse)diContainer[0]);
consumer.DoSomething();
}
}
编辑2:
DI容器是否在“主”方法之外实际使用? 如何在'main'方法之外创建新对象? 让我说我是一些对象深。 我如何在那里创建一个房子?
我在上面的示例中可以使用Asp.Net MVC,其中页面也可以使用IOC容器自动解析。 不幸的是,如果你需要像Asp.Net webforms这样的页面中的DI容器,你应该使用静态的,但只在构造函数中分配对象。 例子(在C#中,我不知道如何使用静态在PHP)。
public class Page1 : Page{
public Page1(){
this.house = CompositionRoot.DiContainer.Create("house");
}
private IHouse house;
}
此实现仍然安全,因为DIContainer仅用于页面的构造函数级别。 但请确保不要在Service类中执行此操作 。 例:
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类的调用者应该通过房屋类。 示例是使用穷人的方式将IRenter类指定给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);
然后你在Page中使用它:
public class Page1 : Page{
public Page1(){
this.renter = (IRenter)CompositionRoot.DiContainer[typeof(IRenter)];
}
private IRenter renter;
}
链接地址: http://www.djcxy.com/p/82093.html
上一篇: Dependency Injection prevent dependency on the dependency container