依赖注入解决循环依赖 [英] Dependency-Injection to resolve circular dependencies

查看:37
本文介绍了依赖注入解决循环依赖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

示例:

class MyClass{成分 m_Composition;无效我的类(){m_Composition = new Composition( this );}}

我有兴趣在这里使用依赖注入.所以我必须将构造函数重构为:

void MyClass( Composition composition ){m_Composition = 组合物;}

但是我现在遇到了一个问题,因为 Composition-object 依赖于刚刚创建的 MyClass 类型的对象.

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

解决方案

,DI Container 不会解决循环依赖 - 事实上,它会抗议当您尝试解决依赖关系时抛出异常.

在许多 DI 容器中,您可以提供高级配置来解决此问题,但它们本身无法解决循环依赖关系.他们怎么可能?

根据经验,循环依赖是一种设计味道.如果可以,请考虑另一种设计,以消除循环依赖 - 这也将使您减少耦合.一些可能的重新设计替代方案:

  • 使用事件从一个班级向另一个班级发出信号.通常,循环依赖已经主要朝着一个方向发展,在这种情况下,将此信令 API 的一部分建模为事件可能会减少循环.
  • 如果上述情况属实,但您觉得事件似乎有误,您可以考虑应用观察者 模式.
  • 如果沟通必须真正双向进行,您可以使用中介,组件通过它可以交流.

然而,我特意选择了 smell 而不是 anti-pattern 这个词,因为在某些极端情况下(特别是当你处理外部定义的 API 时),循环依赖是不可能的避免.

在这种情况下,您需要决定在哪里稍微放松依赖创建.一旦你知道这一点,注入一个抽象工厂可能有助于推迟其中一项创作,直到圆的其他部分已创建.

这个其他答案 是我目前所知道的最好的可用示例,但如果我这么大胆,我即将出版的书也将包含一个部分来解决这个问题.>

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?

解决方案

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:

  • Use events to signal from one class to another. Often a circular dependency already mostly goes in one direction, and when this is the case, modeling part of this signaling API as events may cut the circle.
  • If the above is true, but you feel that events seem wrong, you can consider applying the Observer pattern.
  • If the communication must truly go both ways, you can use a Mediator through which the components can communicate.

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.

这篇关于依赖注入解决循环依赖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆