2010-04-15 12 views
10

He estado leyendo recientemente sobre DI y IoC en C++. Estoy un poco confundido (incluso después de leer preguntas relacionadas aquí en SO) y esperaba alguna aclaración.¿Cuál es la diferencia entre la inversión de control y la inyección de dependencia en C++?

Me parece que estar familiarizado con el STL y Boost conduce al uso de la inyección de dependencia bastante. Por ejemplo, digamos que hice una función que se encuentra la media de una serie de números:

template <typename Iter> 
double mean(Iter first, Iter last) 
{ 
    double sum = 0; 
    size_t number = 0; 
    while (first != last) 
    { 
     sum += *(first++); 
     ++number; 
    } 
    return sum/number; 
}; 

Es éste (es decir, el uso de iteradores en lugar de acceder a la colección en sí) de inyección de dependencia? ¿Inversión de control? ¿Ninguno?

Veamos otro ejemplo. Tenemos una clase:

class Dice 
{ 
public: 
    typedef boost::mt19937 Engine; 
    Dice(int num_dice, Engine& rng) : n_(num_dice), eng_(rng) {} 
    int roll() 
    { 
     int sum = 0; 
     for (int i = 0; i < num_dice; ++i) 
      sum += boost::uniform_int<>(1,6)(eng_); 
     return sum; 
    } 
private: 
    Engine& eng_; 
    int n_; 
}; 

Esto parece una inyección de dependencia. Pero, ¿es inversión de control?

Además, si me falta algo, ¿alguien puede ayudarme? Esta parece ser la forma natural de hacer las cosas, así que si eso es todo lo que hay para Dependency Injection, ¿por qué las personas tienen dificultades para usarlo?

+1

¿Has leído la wiki? Tiene una definición muy clara de IoC/DI http://en.wikipedia.org/wiki/Inversion_of_control – CDSO1

+6

En C++, no hacemos IoC o DI, tenemos nuestros propios conceptos pretenciosos y mal nombrados. –

+0

Su función de plantilla podría dividirse por cero si no tiene cuidado. –

Respuesta

14

Inversion of Control es un concepto muy genérico, con diferentes significados dependiendo del tipo de "control" del que está hablando. La inyección de dependencia es una forma específica.

Inversión de Control y la iteración

En este caso "control" significa "control de flujo".

Creo que su primer ejemplo que implica iteración no es realmente la inversión de control, porque ese código hace explícitamente el control de flujo. La inversión del control separaría la acción a realizar del control de flujo. Se podría tener este aspecto (perdón por mi Java/C#):

SumVisitor sumVisitor = new SumVisitor(); 
collection.AcceptVisitor(sumVisitor); 
int sum = sumVisitor.GetSum(); 

El objeto visitante hace algo para cada elemento de la colección que visita, por ejemplo, actualizar un campo de contador de suma. Pero no tiene control sobre cómo o cuándo es llamado por la colección, de ahí inversión de control. También puede implementar un MedianVisitor, MeanVisitor, MaximumVisitor, etcétera. Cada uno implementa una interfaz genérica IVisitor con un método Visit(Element).

Para la recopilación, ocurre todo lo contrario: no tiene conocimiento de lo que hace el visitante y simplemente se ocupa del control de flujo llamando al visitor.Visit(element) para cada elemento de la colección. Las diferentes implementaciones de visitantes tienen el mismo aspecto para la colección.

Inversión de Control y el gráfico de construcción objeto

En este caso "control" significa "control sobre cómo se crean y se conectan entre sí los componentes".

En cualquier aplicación no trivial, el código se divide en componentes que tienen que colaborar. Para mantener los componentes reutilizables, no se pueden crear directamente entre sí ya que los unirían permanentemente. En cambio, los componentes individuales ceden el control sobre la construcción y el cableado de los componentes.

Dependency injection es una forma de lograr esto, tomando referencias a objetos colaboradores en el constructor. Luego necesita una pieza separada de código de inicio donde todos los componentes se crean y conectan entre sí, o un marco de inyección de dependencia que se ocupa de esto por usted. Su clase de dados es de hecho un ejemplo de inyección de dependencia.

Otra forma de renunciar al control sobre la construcción de gráficos de objetos es el patrón Service Locator, aunque tiene su disadvantages.

1

Déjame intentar responder.

Su primer ejemplo es ninguno de los dos. Es simplemente una plantilla.

Para que sea una inyección de dependencia, se debería haber elegido una IMPLEMENTACIÓN y se debe proporcionar a la plantilla.

Para que sea IoC, la plantilla debería proporcionarse en tiempo de ejecución (no tiempo de compilación) al tipo IMPLEMENTACIÓN, y usarse como la implementación de la función "mean()" (piense en una fábrica que proporcione implementaciones de funciones)

Su segundo ejemplo parece un consumidor de DI/IoC. El código que envía la implementación de Engine a su clase sería el componente DI/IoC.

Afortunadamente, eso es preciso y ayuda.

Cuestiones relacionadas