PHP如何防止疙瘩DIC导致循环依赖的无限循环

时间:2017-03-08 04:04:54

标签: php oop dependency-injection pimple

在这个示例中,我使用了status.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList, Circle>, ObservableValue<Circle>>() { @Override public ObservableValue<Circle> call(TableColumn.CellDataFeatures<ObservableList, Circle> param) { String c = (String) param.getValue().get(2); //getting all data in column 2 of the row System.out.println(c); switch(c){ case "High": circle.setFill(Color.GREEN); healthstatus.setStyle( "-fx-alignment: CENTER;"); break; case "Medium": circle.setFill(Color.YELLOW); healthstatus.setStyle( "-fx-alignment: CENTER;"); break; case "Low": circle.setFill(Color.RED); healthstatus.setStyle( "-fx-alignment: CENTER;"); break; default: circle.setFill(Color.BLUEVIOLET); } return new SimpleObjectProperty(circle); } }); classA我正在使用的疙瘩容器。

他们都彼此依赖。但是当使用疙瘩DIC进行设置时,下面的代码会导致无限循环......

必须有一种方法可以在疙瘩中做到这一点,但我无法在文档中看到它...任何想法如何防止无限循环?

classB

3 个答案:

答案 0 :(得分:2)

@yivi首先对循环引用的有效性做出有效的观察in their answer。所以我真的认为你应该在这里评估你的设计。您可能正在治疗症状,而不是潜在的问题。考虑到你的通用示例代码(这是针对手头问题的优秀代码,我们说),我们不可能对此发表评论。如果您觉得它值得,可能会对您的设计提出一个新问题?在这里或在Code Review,也许?

如果你控制ClassAClassB的设计,那么这种方法的规定方法是使用setter注入,而不是构造函数注入。

这应该有效:

// PIMPLE CONTAINER
use Pimple\Container;
$container = new Container();

use Classes\ClassA;
$container['ClassA'] = function ($c) {
  return new ClassA();
};

use Classes\ClassB;
$container['ClassB'] = function ($c) {
  return new ClassB();
};


$container->extend('ClassA', function ($instanceOfA, $container) {
    $instanceOfA->setB($container['ClassB']);

    return $instanceOfA;
});

$container->extend('ClassB', function ($instanceOfB, $container) {
    $instanceOfB->setA($container['ClassA']);

    return $instanceOfB;
});

(未经测试,可能包含拼写错误,但这是一般要点)

注意原始构造函数如何不再依赖于依赖项,将其插入到特定的setter中。这允许您在容器中创建服务,然后使用extend然后调用相关的setter以在此之后插入依赖项。

这是在文档中:Modifying Services after Definition

答案 1 :(得分:1)

严格来说,你的问题与痘痘有关。

你只是有一个循环构造函数依赖,没有办法解决这些问题。需要B需要A需要B ...

通常情况下,两个相互依赖的类没有多大意义。但是在罕见的情况下,确实会发生这种情况,其中一个应该是一个较轻的依赖,你可以通过一个setter注入对象,或者像实例化后那样的机制

通过传递容器并在ClassB内实例化,您隐藏了依赖项,这与拥有依赖项注入容器的目的相悖。现在ClassB取决于Container,而不是ClassA,这首先是您想要的。

不要这样做,只需向setA(Class A $a)添加方法ClassB

然后,在实际需要时通过调用$b->setA($container['ClassA']);来注入依赖关系,而不是在DI容器上。作为Adam points out,您甚至可以通过扩展服务并在服务定义上使用setter来在容器中执行setter注入。

但是,重申一下,你的主要问题是拥有循环依赖。重新思考一下。它的非常可能是您的设计可以通过一些改进来实现的标志。

答案 2 :(得分:-1)

// PIMPLE CONTAINER
use Pimple\Container;
$container = new Container();

use Classes\ClassA;
$container['ClassA'] = function ($c) {
  return new ClassA($c['ClassB']);
};

use Classes\ClassB;
$container['ClassB'] = function ($c) {
  return new ClassB($c);
};

不是从classB实例化ClassA,而是将容器传递给ClassB。然后,当您需要ClassB中的ClassA时,您可以使用传递给它的容器来启动/获取ClassA的实例。