1

我一直在我的 PHP 应用程序中练习构造函数依赖注入。我不想在我的代码中乱扔对象创建,所以工厂来救援,或者至少我认为。

我开始用工厂连接组件,然后一些工厂开始使用其他工厂来获取依赖关系,太好了,将所有创建代码保存在一个地方。但是,一旦工厂开始相互使用(或在下面的代码中,本身),我遇到了循环依赖问题,这根本无法解决。例如,我的 MapperFactory 使用自己将映射器与其他映射器注入(它们需要彼此来构建完整的对象图“急切加载”):

class MapperFactory
{   
    public function create($type)
    {
        switch (true) {
            case 'Item':
                $mapper = new ItemMapper(
                    $this->create('Field')  
                );               
                break;
            case 'Field':
                $mapper = new ItemMapper(
                    $this->create('Item')  
                );
                break;
            default:
                throw new Exception('Unknown mapper');
        }
        return $mapper;
    }

}

$mf = new MapperFactory();
$mf->create('Item');

它是一个简化的示例,但随着应用程序的开发,这是一个越来越普遍的问题。从 PHP(安装了 xdebug)返回的错误是:

Fatal error: Maximum function nesting level of '100' reached, aborting!

完全理解 PHP 抱怨的原因(虽然 TBH 没有看到它)。

我的问题是,我是否完全错过了工厂的意义?我是否正确使用工厂?看起来不是,但除了循环依赖(非常重要)之外,工厂是一种优雅的解决方案,可以将所有构造/接线逻辑隐藏在主应用程序之外。

4

2 回答 2

1

您可以尝试使用 setter 来注入依赖项。然后你会像这样创建两个映射器:

$itemMapper = new Mapper();
$fieldMapper = new Mapper();
$itemMapper->setRelatedMapper($fieldMapper);
$fieldMapper->setRelatedMapper($itemMapper);

然后使用开关返回映射器。这应该在创建对象时摆脱循环依赖。

话虽如此,如果您将其作为一种 OR/M 操作来连接到数据库,您可能应该研究 Doctrine2 或 Propel 之类的东西,只是为了省去在已经尝试过的情况下发明轮子的麻烦经过测试的解决方案。

于 2012-08-13T17:57:09.807 回答
0

看起来MapperFactory' create方法会导致无限循环。

switch(true) {
  case 'Item' : // this will always be selected http://php.net/manual/en/language.types.type-juggling.php
    $mapper = new ItemMapper(
      $this->create('Field'); // Forces loop,
    );

如果 switch 正在寻找TRUE匹配,那么 case 操作必须是一个布尔值

switch(true) {
  case $type == 'Item' :
    // ...
    break;
  case $type == 'Field' :
    // ...
 }
于 2012-08-13T17:57:29.167 回答