2010-04-15 3 views
10

J'ai lu récemment sur DI et IoC en C++. Je suis un peu confus (même après avoir lu des questions connexes ici sur SO) et j'espérais une clarification.Quelle est la différence entre l'inversion de contrôle et l'injection de dépendance en C++?

Il me semble qu'être familier avec le STL et le Boost conduit à l'utilisation de l'injection de dépendance un peu. Par exemple, disons que je fait une fonction que l'on trouve la moyenne d'une série de chiffres:

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; 
}; 

Est-ce (à savoir l'utilisation d'itérateurs au lieu d'accéder à la collection elle-même) d'injection de dépendance? Inversion de contrôle? Ni?

Regardons un autre exemple. Nous avons une classe:

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_; 
}; 

Cela ressemble à une injection de dépendance. Mais est-ce l'inversion du contrôle?

Aussi, si quelque chose me manque, quelqu'un peut-il m'aider? Cela semble être la façon naturelle de faire les choses, donc si c'est tout ce qu'il ya à l'injection de dépendance, pourquoi les gens ont du mal à l'utiliser?

+1

Avez-vous lu le wiki? Il a une définition très claire de IoC/DI http://en.wikipedia.org/wiki/Inversion_of_control – CDSO1

+6

En C++, nous ne faisons pas IoC ou DI - nous avons nos propres concepts prétentieux et mal nommés. –

+0

Votre fonction de modèle pourrait diviser par zéro si vous ne faites pas attention. –

Répondre

14

Inversion of Control est un concept très générique, avec des significations différentes selon le type de "contrôle" dont vous parlez. L'injection de dépendance est une forme spécifique.

et Inversion de contrôle itération

Dans ce cas, le "contrôle" signifie "contrôle de flux".

Je pense que votre premier exemple impliquant l'itération n'est pas vraiment une inversion de contrôle, car ce code effectue explicitement le contrôle de flux. L'inversion du contrôle séparerait l'action à effectuer du contrôle de flux. Il pourrait ressembler à ceci (pardonnez mon java/C#):

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

L'objet visiteur fait quelque chose pour chaque élément de collection, il se rend, par exemple mettre à jour un champ de compteur de somme. Mais il n'a aucun contrôle sur comment ou quand il est appelé par la collection, d'où inversion du contrôle. Vous pouvez également implémenter un MedianVisitor, MeanVisitor, MaximumVisitor, etcetera. Chacun d'eux implémente une interface générique IVisitor avec une méthode Visit(Element).

Pour la collection, l'inverse est vrai: elle n'a aucune connaissance de ce que fait le visiteur et s'occupe simplement du contrôle de flux en appelant le visitor.Visit(element) pour chaque élément de la collection. Différentes implémentations de visiteurs se ressemblent toutes pour la collection.

et inversion de contrôle de construction objet graphique

Dans ce cas, le « contrôle » signifie « le contrôle sur la façon dont les composants sont créés et câblés ensemble ».

Dans toute application non triviale, le code est divisé en composants qui doivent collaborer. Pour conserver les composants réutilisables, ils ne peuvent pas se créer directement car cela les collerait ensemble de façon permanente. Au lieu de cela, les composants individuels abandonnent le contrôle sur la construction et le câblage des composants.

Dependency injection est un moyen d'y parvenir en prenant des références aux objets collaborateurs dans le constructeur. Vous avez alors besoin d'un morceau de code de démarrage séparé où tous les composants sont créés et câblés ensemble, ou d'un cadre d'injection de dépendance qui prend soin de cela pour vous. Votre classe Dice est en effet un exemple d'injection de dépendance.

Une autre façon d'abandonner le contrôle sur la construction de graphe d'objet est le motif Service Locator, bien qu'il ait son disadvantages.

1

Laissez-moi essayer de répondre.

Votre premier exemple n'est ni. C'est simplement un modèle. Pour qu'il s'agisse d'une injection de dépendance, il aurait fallu choisir une MISE EN ŒUVRE et la fournir au gabarit. Pour qu'il soit IoC, le template devrait être fourni à l'exécution (pas au temps de compilation) au type IMPLEMENTATION, et utilisé comme implémentation de la fonction "mean()" (pensez à une usine qui fournit des moyennes implémentations de fonction)

Votre deuxième exemple ressemble à un consommateur de DI/IoC. Le code qui envoie l'implémentation de Engine dans votre classe est le composant DI/IoC.

Espérons que cela soit précis et utile.

Questions connexes