PHP延迟加载对象和依赖注入

16 浏览
0 Comments

PHP延迟加载对象和依赖注入

最近我开始阅读关于依赖注入的内容,这让我重新思考了一些设计问题。

我遇到的问题大致如下:

假设我有两个类:Car(汽车)和Passenger(乘客);

针对这两个类,我有一些数据映射器可以与数据库交互:CarDataMapper和PassengerDataMapper。

我希望在代码中能够像这样实现:

$car = CarDataMapper->getCarById(23); // 返回汽车对象
foreach($car->getPassengers() as $passenger){ // 返回该汽车的所有乘客
    $passenger->doSomething();
}

在了解依赖注入之前,我会像这样构建我的类:

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:将数据映射器注入到Car和Passenger对象中,并像这样使用:

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;  
    }
}

我同样不喜欢这种方法,因为Car并不真正不知道数据映射器,而且没有数据映射器,Car的行为可能是不可预测的(当实际上它有乘客时不返回乘客)。

所以我的第一个问题是:

我这样做的方法完全错误吗?因为越看越像我在构建ORM而不是业务层。

第二个问题是:

是否有一种方式可以真正解耦对象和数据映射器,以便我可以像在最初的代码块中描述的那样使用对象?

第三个问题:

我看到其他语言(我想是某个版本的C)的一些答案解决了这个问题,像这里描述的那样:

What is the proper way to inject a data access dependency for lazy loading?

由于我没有时间尝试其他语言,所以这对我来说没有意义,所以如果有人能用类似于PHP的语言解释链接中的示例,我将不胜感激。

我也看过一些依赖注入框架,并了解了依赖注入容器和控制反转,但据我所理解,它们用于定义和注入“非动态”类的依赖项,例如Car依赖于Engine,但它不需要从数据库动态加载Engine,只需实例化并注入到Car中。

对于这篇冗长的帖子我表示抱歉,提前感谢您的帮助。

0