2010-04-09 9 views
10

Ejemplo:Dependencia-inyección para resolver dependencias circulares

class MyClass 
{ 
    Composition m_Composition; 

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

Estoy interesado en el uso de la inyección depenency aquí. Así que voy a tener que refactorizar el constructor para algo como:

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

Sin embargo consigo un problema ahora, ya que el Composition -objeto se basa en el objeto de tipo MyClass que se acaba de crear.

¿Puede un contenedor de dependencia resolver esto? ¿Se supone que debe hacerlo?
¿O es solo un mal diseño desde el principio?

Respuesta

11

Sin, un DI de contenedores no va a resolver una dependencia circular - de hecho, se protestará contra él por lanzar excepciones cuando intenta resolver las dependencias.

En muchos de los Contenedores DI puede proporcionar una configuración avanzada que le permite superar este problema, pero ellos solos no pueden resolver las dependencias circulares. ¿Como pudireon?

Como regla general, una dependencia circular es olor de diseño. Si puede, considere un diseño alternativo donde se deshaga de la dependencia circular; esto también le dará menos acoplamiento. Algunas posibles alternativas de rediseño:

  • Use eventos a la señal de una clase a otra. A menudo, una dependencia circular ya va en una dirección, y cuando este es el caso, modelar parte de esta API de señalización como eventos puede cortar el círculo.
  • Si lo anterior es cierto, pero siente que los eventos parecen incorrectos, puede considerar aplicar el patrón Observer.
  • Si la comunicación debe ir realmente en ambos sentidos, puede usar un Mediator a través del cual los componentes se pueden comunicar.

Sin embargo, purposedly eligió la palabra olor sobre anti-patrón, ya que hay casos de esquina (en particular cuando se trabaja con las API definidas externamente), donde dependencias circulares no pueden ser evitados.

En tales casos, debe decidir dónde aflojar ligeramente la creación de la dependencia. Una vez que lo sepa, la inyección de un Abstract Factory puede ser útil para diferir una de las creaciones hasta que se hayan creado las otras partes del círculo.

Este other answer es el mejor ejemplo disponible del que tengo conocimiento en la actualidad, pero si soy tan audaz, mi próximo libro también incluirá una sección que aborda este tema.

+0

Gracias por la respuesta. Trataré de averiguar si puedo evitar la referencia circular en mi caso, aunque todavía no estoy seguro: necesito la referencia para suscribirme a algunos eventos de MyClass dentro del constructor de Composition ... Gracias por mencionar su libro, que suena muy interesante. Estoy deseando leerlo. – tanascius

+0

Para ser claros: aunque ya puede comprar acceso anticipado al libro, la sección sobre el tratamiento de referencias circulares aún no está disponible. –

Cuestiones relacionadas