2010-04-09 214 views
10

例子:依赖注入解决循环依赖

class MyClass 
{ 
    Composition m_Composition; 

    void MyClass() 
    { 
     m_Composition = new Composition(this); 
    } 
} 

我很感兴趣,这里使用depenency注射。因此,我将不得不构造重构的东西,如:

void MyClass(Composition composition) 
{ 
    m_Composition = composition; 
} 

但是我现在得到一个问题,因为Composition -object依靠其刚刚创建MyClass类型的对象。

依赖项容器可以解决这个问题吗?它应该这样做吗?
还是从一开始就只是糟糕的设计?

回答

11

没有,一个DI容器不会解决循环依赖 - 事实上,它会抗议它通过抛出异常,当您尝试解决的依赖关系。

在许多DI容器中,您可以提供高级配置,使您可以解决此问题,但是它们本身无法解决循环依赖关系。他们怎么可能?作为一个经验法则,循环依赖是设计气味

作为一个经验法则,循环依赖是设计气味。如果可以的话,考虑一个替代设计,你可以摆脱循环依赖 - 这也会给你减少耦合。一些可能的替代方案的重新设计:

  • 使用事件信号从一类到另一个。通常情况下,循环依赖已经大部分都朝着一个方向发展,并且在这种情况下,将此信令API的一部分建模为事件可能会削减该循环。
  • 如果以上情况属实,但您认为事件看起来不正确,则可以考虑应用Observer模式。
  • 如果通信必须真正走向双向,则可以使用组件可以通信的Mediator

不过,我刻意的选择了字气味超过反模式,因为有其他的情况(特别是当你处理外部定义的API),其中无法避免循环依赖。

在这种情况下,您需要决定稍微放松依赖关系创建的位置。一旦你知道了,注入一个Abstract Factory可能会有助于延迟其中一个创建,直到创建了该圆的其他部分。

这个other answer是我目前知道的最好的,可用的例子,但如果我可能如此大胆,我即将出版的书也将包含一个解决这个问题的部分。

+0

感谢您的回答。我会试着找出在我的情况下是否可以避免循环引用,虽然我不确定,但是:我需要引用来订阅Composition的构造函数中的MyClass的一些事件...感谢您提及您的书,它听起来很有趣。我期待着阅读它。 – tanascius 2010-04-14 11:16:39

+0

要清楚:尽管您已经可以购买该书的早期访问权限,但关于处理循环引用的部分尚不可用。 – 2010-04-14 11:54:18