我最近开始阅读关于依赖注入的知识,它让我重新思考一些我的设计。PHP懒惰加载对象和依赖项注入
我的问题是这样的: 比方说,我有两个类:车客; 对于这两个类,我有一些数据映射器与数据库的工作:CarDataMapper和PassengerDataMapper
我希望能够在代码中做这样的事情:
$car = CarDataMapper->getCarById(23); // returns the car object
foreach($car->getPassengers() as $passenger){ // returns all passengers of that car
$passenger->doSomething();
}
之前,我知道DI什么,我将建立我的课是这样的:
class Car {
private $_id;
private $_passengers = null;
public function getPassengers(){
if($this->_passengers === null){
$passengerDataMapper = new PassengerDataMapper;
$passengers = $passengerDataMapper->getPassengersByCarId($this->getId());
$this->setPassengers($passengers);
}
return $this->_passengers;
}
}
我也有类似的代码在Passenger-> getCar()方法来获取车里的乘客在
。我现在明白,这会在Car和Passenger对象和数据映射器对象之间创建依赖关系(当然,我也了解它,但我并不知道这是“错误的”)。
虽然冥思苦想此两个选项的解决方案来考虑,但我真的不喜欢任何人:
1:做这样的事情:
$car = $carDataMapper->getCarById(23);
$passengers = $passengerDataMapper->getPassengersByCarId($car->getId());
$car->setPassengers($passengers);
foreach($car->getPassengers() as $passenger){
$passenger->doSomething();
}
但什么如果乘客有需要注入的对象,并且如果嵌套达到十到二十个层次,我会结束实例化几乎每个对象,在我的应用程序开始时,它会在整个过程中查询整个数据库。 如果我必须将乘客发送给另一个必须对乘客所持物品进行操作的物体,我不想立即将这些物体实例化。
2:注入数据映射器到汽车和乘客的对象,并且具有这样的事情:
class Car {
private $_id;
private $_passengers = null;
private $_dataMapper = null;
public function __construct($dataMapper){
$this->setDataMapper($dataMapper);
}
public function getPassengers(){
if($this->_passengers === null && $this->_dataMapper instanceof PassengerDataMapper){
$passengers = $this->_dataMapper->getPassengersByCarId($this->getId());
$this->setPassengers($passengers);
}
return $this->_passengers;
}
}
我不喜欢这样更好,因为它不喜欢的车是真的不知道数据映射器,并没有数据映射器,汽车可能表现不可预知(不返回乘客,当它实际上有他们)
所以我的第一个问题是: 我在这里采取了一个完全错误的方法,因为越多我看它,它看起来越像我构建一个ORM,而不是一个业务层?
第二个问题是: 是否有一种方法可以实际将对象和数据映射器分离开来,这样就可以使用第一个代码块中描述的对象?
第三个问题: 我已经看到了其他语言解决这个问题的是这样一些答案(有些版本的C,我认为)这里描述: What is the proper way to inject a data access dependency for lazy loading? 由于我没有来得及与其他玩语言,这对我来说没有意义,所以如果有人会在PHP-ish的链接中解释这些例子,我将不胜感激。
我也查看了一些DI框架,并阅读了关于DI Containers和Inversion of Control的内容,但是根据我的理解,它们用于定义和注入“非动态”类的依赖关系,例如Car依赖于引擎,但它不需要从数据库动态加载引擎,它只会被实例化并注入汽车。
对不起,冗长的职位,并提前感谢。
您可能想要结帐[PoEAA](http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420/ref=sr_1_1?ie=UTF8&qid=1350785602&sr=8-1&keywords=模式+ +企业+应用程序+架构)虽然它根本无法帮助[DI](http://martinfowler.com/articles/injection.html)(它早于共同点),但您会意识到,即使您业务层您需要一个位于其下的ORM。建议使用[Data Mapper](http://martinfowler.com/eaaCatalog/dataMapper.html)。 +1提出我一直在寻找答案的问题。 – xenoterracide 2012-10-21 02:16:06
感谢您的提示。最近我在我的大部分项目中都使用了Doctrine2,这是一个Data Mapper ORM,并且很容易处理。 – Pinetree 2012-10-21 06:02:28