Question Injection de dépendance par rapport au modèle d'usine


La plupart des exemples cités pour l'utilisation de Dependency Injection, nous pouvons résoudre en utilisant le modèle d'usine aussi bien. On dirait que quand il s'agit d'utilisation / conception, la différence entre l'injection de dépendance et l'usine est floue ou mince.

Une fois que quelqu'un m'a dit que c'est la façon dont vous l'utilisez qui fait la différence!

J'ai déjà utilisé StructureMap un conteneur DI pour résoudre un problème, plus tard je l'ai redessiné pour travailler avec une usine simple et supprimé des références à StructureMap.

Quelqu'un peut-il me dire quelle est la différence entre eux et où utiliser quoi, quelle est la meilleure pratique ici?


416
2018-02-17 17:14


origine


Réponses:


Lorsque vous utilisez une fabrique, votre code est toujours responsable de la création d'objets. Par DI vous externaliser cette responsabilité à une autre classe ou un cadre, qui est séparé de votre code.


251
2018-02-17 17:10



Je suggère de garder les concepts simples et simples. La dépendance par injection est plutôt un modèle architectural permettant de coupler librement des composants logiciels. Le motif d'usine n'est qu'un moyen de séparer la responsabilité de créer des objets d'autres classes avec une autre entité. Le modèle d'usine peut être appelé comme un outil pour mettre en œuvre DI. L'injection de dépendances peut être implémentée de plusieurs façons, comme DI en utilisant des constructeurs, en utilisant des fichiers XML de mappage, etc.


191
2018-06-04 06:06



Injection de dépendance

Au lieu d'instancier les pièces elles-mêmes, une voiture demande pour les pièces dont il a besoin pour fonctionner.

class Car
{
    private Engine;
    private SteeringWheel;
    private Tires tires;

    public Car(Engine engine, SteeringWheel wheel, Tires tires)
    {
        this.Engine = engine;
        this.SteeringWheel = wheel;
        this.Tires = tires;
    }
}

Usine

Met les pièces ensemble pour faire un objet complet et cache le type de béton de l'appelant.

static class CarFactory
{
    public ICar BuildCar()
    {
        Engine engine = new Engine();
        SteeringWheel steeringWheel = new SteeringWheel();
        Tires tires = new Tires();
        ICar car = new RaceCar(engine, steeringWheel, tires);
        return car;
    }   
}

Résultat

Comme vous pouvez le voir, les usines et DI se complètent.

static void Main()
{
     ICar car = CarFactory.BuildCar();
     // use car
}

Vous souvenez-vous des boucles d'or et des trois ours? Eh bien, l'injection de dépendance est un peu comme ça. Voici trois façons de faire la même chose.

void RaceCar() // example #1
{
    ICar car = CarFactory.BuildCar();
    car.Race();
}

void RaceCar(ICarFactory carFactory) // example #2
{
    ICar car = carFactory.BuildCar();
    car.Race();
}

void RaceCar(ICar car) // example #3
{
    car.Race();
}

Exemple 1 - C'est le pire parce qu'il cache complètement la dépendance. Si vous regardiez la méthode comme une boîte noire, vous n'auriez aucune idée qu'il fallait une voiture.

Exemple # 2 - C'est un peu mieux car maintenant nous savons que nous avons besoin d'une voiture puisque nous passons dans une usine automobile. Mais cette fois, nous passons trop car toute la méthode dont nous avons besoin est une voiture. Nous passons dans une usine juste pour construire la voiture quand la voiture pourrait être construite en dehors de la méthode et passée.

Exemple # 3 - C'est idéal car la méthode demande exactement ce dont il a besoin Pas trop ou trop peu. Je n'ai pas besoin d'écrire un MockCarFactory uniquement pour créer des MockCars, je peux passer le simulacre directement. C'est direct et l'interface ne repose pas.

Ce Google Tech Talk par Misko Hevery est incroyable et est la base de ce que j'ai dérivé de mon exemple. http://www.youtube.com/watch?v=XcT4yYu_TTs


145
2018-02-17 17:16



Il y a des problèmes qui sont faciles à résoudre avec l'injection de dépendance qui ne sont pas si facilement résolus avec une suite d'usines.

Une partie de la différence entre, d’une part, l’inversion du contrôle et l’injection de dépendance (IOC / DI) et, d’autre part, un localisateur de services ou une suite d’usines (usine), est:

IOC / DI est un écosystème complet d'objets et de services de domaine en soi. Tout est mis en place selon vos spécifications. Vos objets et services de domaine sont construits par le conteneur et ne se construisent pas eux-mêmes: ils n'ont donc pas tout dépendances sur le conteneur ou sur toutes les usines. IOC / DI permet un très haut degré de configurabilité, avec toute la configuration en un seul endroit (construction du conteneur) à la couche supérieure de votre application (l'interface graphique, l'interface Web).

Factory élimine une partie de la construction de vos objets et services de domaine. Mais les objets et les services du domaine sont toujours responsables de comprendre comment se construire et comment obtenir toutes les choses dont ils dépendent. Toutes ces dépendances "actives" filtrent à travers toutes les couches de votre application. Il n'y a pas d'endroit unique pour tout configurer.


38
2018-02-17 17:13



Un inconvénient de DI est qu'il ne peut pas initialiser des objets avec la logique. Par exemple, lorsque je dois créer un personnage qui a un nom et un âge aléatoires, DI n'est pas le choix par rapport au motif d'usine. Avec les usines, nous pouvons facilement encapsuler l'algorithme aléatoire de la création d'objet, qui prend en charge l'un des modèles de conception appelé «Encapsuler ce qui varie».


21
2018-02-17 17:12



La gestion du cycle de vie est l'une des responsabilités assumées par les conteneurs de dépendance en plus de l'instanciation et de l'injection. Le fait que le conteneur conserve parfois une référence aux composants après l'instanciation est la raison pour laquelle il est appelé un "conteneur", et non une usine. Les conteneurs d'injection de dépendances ne conservent généralement qu'une référence aux objets dont ils ont besoin pour gérer les cycles de vie, ou qui sont réutilisés pour des injections futures, comme les singletons ou les poids volants. Lorsqu'il est configuré pour créer de nouvelles instances de certains composants pour chaque appel au conteneur, le conteneur oublie généralement l'objet créé.

De: http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html


19
2018-02-17 18:01



La raison pour laquelle l'injection de dépendances (ID) et les motifs d'usine sont similaires est due au fait qu'il s'agit de deux implémentations de l'Inversion de Contrôle (IoC) qui est une architecture logicielle. Dit simplement, ce sont deux solutions au même problème.

Donc, pour répondre à la question, la principale différence entre le motif Factory et DI est la façon dont la référence d'objet est obtenue. Avec l'injection de dépendance comme son nom l'indique, la référence est injectée ou donnée à votre code. Avec le motif Factory, votre code doit demander la référence afin que votre code récupère l'objet. Les deux implémentations suppriment ou découplent la liaison entre le code et la classe sous-jacente ou le type de la référence d'objet utilisée par le code.

Il convient de noter que les modèles d'usine (ou les modèles d'usine abstraite qui sont des usines renvoyant de nouvelles usines renvoyant des références d'objet) peuvent être écrits pour choisir dynamiquement le type ou la classe d'objet demandé lors de l'exécution. Cela les rend très similaires (encore plus que DI) au modèle de Localisateur de Service qui est une autre implémentation de l'IoC.

Le modèle de conception d'usine est assez vieux (en termes de logiciel) et a été autour pendant un moment. Depuis la récente popularité du modèle architectural, IoC connaît un regain.

En ce qui concerne les modèles de conception de l'IoC, je suppose: les injecteurs sont injectés, les localisateurs sont localisés et les usines ont été remises à neuf.


19
2018-02-17 19:02



Je crois que le DI est un type de couche d'abstraction sur les usines, mais elles offrent également des avantages au-delà de l'abstraction. Une véritable usine sait comment instancier un seul type et le configurer. Une bonne couche DI permet, grâce à la configuration, d'instancier et de configurer de nombreux types.

De toute évidence, pour un projet avec quelques types simples qui nécessite une logique métier relativement stable dans leur construction, le modèle d'usine est simple à comprendre, à mettre en œuvre et fonctionne bien.

OTOH, si vous avez un projet contenant de nombreux types dont vous prévoyez de changer souvent les implémentations, DI vous donne la flexibilité grâce à sa configuration de faire cela à l'exécution sans avoir à recompiler vos usines.


16