依赖注入解决循环依赖

发布于 2024-08-28 06:39:51 字数 472 浏览 7 评论 0原文

示例:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ゃ懵逼小萝莉 2024-09-04 06:39:51

,DI 容器不会解决循环依赖 - 事实上,当您尝试解决依赖项时,它会通过抛出异常来抗议。

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

根据经验,循环依赖是一种设计味道。如果可以的话,考虑一种摆脱循环依赖的替代设计 - 这也会给你带来更少的耦合。一些可能的重新设计替代方案:

  • 使用事件从一个类向另一个类发出信号。通常,循环依赖大部分都朝一个方向发展,在这种情况下,将此信号 API 的一部分建模为事件可能会缩短循环。
  • 如果上述情况成立,但您觉得事件似乎有问题,则可以考虑应用 观察者 模式。
  • 如果通信必须真正双向进行,您可以使用 Mediator 组件可以通过它进行通信。

然而,我特意选择了“气味”一词而不是“反模式”,因为在某些极端情况下(特别是当您处理外部定义的 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:

  • 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文