Зависимость-инъекция для решения круговых зависимостей

Пример:

class MyClass
{
    Composition m_Composition;

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

Меня интересует использование инъекции отпусков. Поэтому мне придется реорганизовать конструктор на что-то вроде:

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

Однако теперь я получаю проблему, так как объект Composition -объект полагается только на объект типа MyClass.

Может ли контейнер зависимостей разрешить это? Предполагается ли это сделать?
Или это просто плохой дизайн с самого начала?

Ответ 1

Нет, контейнер DI не решит круговую зависимость - на самом деле, он протестует против этого, бросая исключения при попытке разрешить зависимости.

Во многих контейнерах DI вы можете предоставить расширенную конфигурацию, которая позволяет вам преодолеть эту проблему, но сама по себе они не могут разрешать круговые зависимости. Как они могли?

Как правило, круговая depedency - это дизайн запаха. Если можно, рассмотрите альтернативный дизайн, в котором вы избавитесь от круговой зависимости - это также даст вам меньше связи. Возможные альтернативы редизайна:

  • Используйте события для передачи сигналов от одного класса другому. Часто круговая зависимость уже в основном идет в одном направлении, и, когда это так, моделирование части этого сигнального API как события может обрезать круг.
  • Если это верно, но вы считаете, что события кажутся неправильными, вы можете рассмотреть возможность применения шаблона Observer.
  • Если сообщение действительно должно идти в обоих направлениях, вы можете использовать Mediator, через который эти компоненты могут связываться.

Однако я специально выбрал слово "запах" над анти-шаблоном, так как есть угловые случаи (особенно когда вы имеете дело с внешними определенными API-интерфейсами), где нельзя избежать циклических зависимостей.

В таких случаях вам нужно решить, где немного ослабить создание зависимостей. Как только вы это знаете, инъекция Аннотация Factory может быть полезна для отсрочки одного из созданий до тех пор, пока другие части круга не будут создан.

Этот другой ответ - лучший, доступный пример, о котором я сейчас знаю, но если я могу быть таким смелым, в моей предстоящей книге также будет раздел который затрагивает эту самую проблему.