依赖注入解决循环依赖
示例:
class MyClass
{
Composition m_Composition;
void MyClass()
{
m_Composition = new Composition( this );
}
}
我对在这里使用依赖注入感兴趣。因此,我必须将构造函数重构为以下内容:
void MyClass( Composition composition )
{
m_Composition = composition;
}
但是,我现在遇到了一个问题,因为 Composition
对象依赖于刚刚创建的 MyClass
类型的对象。
依赖容器可以解决这个问题吗?它应该这样做吗?
或者这只是从一开始就糟糕的设计?
Example:
class MyClass
{
Composition m_Composition;
void MyClass()
{
m_Composition = new Composition( this );
}
}
I am interested in using depenency-injection here. So I will have to refactor the constructor to something like:
void MyClass( Composition composition )
{
m_Composition = composition;
}
However I get a problem now, since the Composition
-object relies on the object of type MyClass
which is just created.
Can a dependency container resolve this? Is it supposed to do so?
Or is it just bad design from the beginning on?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不,DI 容器不会解决循环依赖 - 事实上,当您尝试解决依赖项时,它会通过抛出异常来抗议。
在许多 DI 容器中,您可以提供高级配置来克服此问题,但它们本身无法解决循环依赖关系。他们怎么能呢?
根据经验,循环依赖是一种设计味道。如果可以的话,考虑一种摆脱循环依赖的替代设计 - 这也会给你带来更少的耦合。一些可能的重新设计替代方案:
然而,我特意选择了“气味”一词而不是“反模式”,因为在某些极端情况下(特别是当您处理外部定义的 API 时)无法避免循环依赖。
在这种情况下,您需要决定在哪里稍微放松依赖关系的创建。一旦您知道这一点,注入抽象工厂可能有助于推迟其中一项创作,直到圆的其他部分已经创建。
这其他答案是我目前所知的最好的可用示例,但如果我可以如此大胆,我即将出版的书也将包含解决这个问题的部分。
No, a DI Container will not solve a circular dependency - in fact, it will protest against it by throwing exceptions when you try to resolve the dependencies.
In many of the DI Containers you can provide advanced configuration that allows you to overcome this issue, but by themselves they can't resolve circular dependencies. How could they?
As a rule of thumb, a circular depedency is a design smell. If you can, consider an alternative design where you get rid of the circular dependency - this will also give you less coupling. Some possible redesign alternatives:
However, I purposedly chose the word smell over anti-pattern, as there are corner cases (particularly when you deal with externally defined APIs) where circular dependencies cannot be avoided.
In such cases, you need to decide where to loosen the dependency creation slightly. Once you know that, injection of an Abstract Factory may be helpful to defer one of the creations until the other parts of the circle have been created.
This other answer is the best, available example of which I'm currently aware, but if I may be so bold, my upcoming book will also contain a section that addresses this very issue.