与工厂的依赖注入

时间:2012-08-13 17:19:19

标签: php dependency-injection factory

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

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

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)。

我的问题是,我是否完全错过了工厂的观点?我正确使用工厂吗?它似乎不是,但除了循环依赖(非常重要但是)之外,工厂是一种优雅的解决方案,可以将所有构造/布线逻辑隐藏在主应用之外。

2 个答案:

答案 0 :(得分:1)

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

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

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

话虽如此,如果你把它作为一种连接到数据库的OR / M的东西,你应该看看像Doctrine2或Propel这样的东西,只是为了省去发明轮子的麻烦。已经经过试验和测试的解决方案。

答案 1 :(得分:0)

看起来MapperFactory的{​​{1}}方法导致无限循环。

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, ); 匹配,则case操作必须是布尔值

TRUE