525 votes

Injection de dépendances et modèle de fabrique

La plupart des exemples cités pour l'utilisation de l'injection de dépendance, nous pouvons également les résoudre en utilisant le modèle de fabrique. Il semble que lorsqu'il s'agit d'utilisation/conception, la différence entre l'injection de dépendance et la fabrique est floue ou mince.

Quelqu'un m'a dit un jour que c'est la façon dont on l'utilise qui fait la différence !

J'ai utilisé une fois StructureMap un conteneur DI pour résoudre un problème, plus tard, je l'ai redessiné pour qu'il fonctionne avec une simple usine et j'ai supprimé les 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 ?

23 votes

Ces deux approches ne peuvent-elles pas se compléter l'une l'autre : utiliser l'injection de dépendances pour injecter des classes d'usine ?

21 votes

Ce serait vraiment bien si cette question avait une réponse avec du code ! Je ne vois toujours pas en quoi DI serait bénéfique/différent de l'utilisation d'une factory pour la création ? Il suffit de remplacer cette ligne dans la classe factory pour changer l'objet/implémentation qui est créé ?

2 votes

@gideon cela ne vous obligerait-il pas à compiler votre application, ou au moins le module contenant la classe d'usine ?

302voto

willcodejavaforfood Points 20365

Lorsque vous utilisez une fabrique, votre code est toujours responsable de la création des objets. Avec DI, vous externalisez cette responsabilité à une autre classe ou à un framework, qui est séparé de votre code.

180 votes

Le modèle DI ne nécessite aucun cadre. Vous pouvez faire du DI en écrivant manuellement des fabriques qui font du DI. Les frameworks DI ne font que faciliter les choses.

29 votes

@Perpetualcoder - Merci @Esko - Ne vous laissez pas entraîner par le mot "framework" qui signifie une bibliothèque avancée d'un tiers.

0 votes

Pourriez-vous dire quel est l'avantage de donner à DI la responsabilité de la création ? Dans le cas de la méthode factory, il suffit de modifier une ligne de code pour changer l'implémentation qui est créée, n'est-ce pas ?

231voto

Perpetualcoder Points 7381

Je vous suggère de garder les concepts simples et clairs. L'injection de dépendances est plutôt un modèle architectural permettant de coupler librement des composants logiciels. Le Factory pattern est juste un moyen de séparer la responsabilité de la création d'objets d'autres classes à une autre entité. Le Factory pattern peut être appelé un outil pour implémenter l'injection de dépendances. L'injection de dépendances peut être mise en œuvre de nombreuses façons, par exemple en utilisant des constructeurs, des fichiers xml de mappage, etc.

4 votes

Il est vrai que le Factory Pattern est l'un des moyens d'implémenter l'injection de dépendance. Un autre avantage de l'utilisation de l'injection de dépendances par rapport au Factory Pattern est que les Frameworks DI vous donnent la flexibilité de la manière d'enregistrer vos abstractions par rapport à vos types concrets. Par exemple, Code as Config, XML ou Auto Configuration. Cette flexibilité vous permettra de gérer la durée de vie de vos objets ou de décider comment et quand enregistrer vos interfaces.

2 votes

Le modèle Factory offre une abstraction de plus haut niveau que DI. Une fabrique peut offrir des options de configuration, comme le fait DI, mais elle peut aussi choisir de cacher tous ces détails de configuration, de sorte que la fabrique peut décider de passer à une implémentation complètement différente sans que le client le sache. DI en soi ne permet pas cela. DI exige du client qu'il spécifie les changements qu'il souhaite.

1 votes

Belle réponse. Beaucoup sont déroutés par cette question : "Quels patrons dois-je choisir ?" En fait, les patrons de conception ne sont qu'un moyen de résoudre des problèmes dans des situations appropriées. Si vous ne savez pas quel design pattern vous devez utiliser, ou "Où dois-je implémenter le pattern ?", alors vous n'en avez pas besoin pour le moment.

210voto

Despertar Points 5365

Injection de dépendances

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 engine;
    private SteeringWheel wheel;
    private Tires tires;

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

Usine

Assemble les pièces pour former un objet complet et cache le type concret à 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 constater, les usines et l'ID se complètent.

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

Tu te souviens de Boucle d'or et les trois ours ? Eh bien, l'injection de dépendances 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 n° 1 - C'est le pire car il masque complètement la dépendance. Si vous regardiez la méthode comme une boîte noire, vous n'auriez aucune idée qu'elle nécessite une voiture.

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

Exemple n° 3 - C'est idéal car la méthode demande exactement ce dont il a besoin. Ni trop, ni trop peu. Je n'ai pas besoin d'écrire un MockCarFactory juste pour créer des MockCars, je peux passer le mock directement dedans. C'est direct et l'interface ne ment pas.

Ce Google Tech Talk de Misko Hevery est étonnant et constitue la base de ce dont j'ai tiré mon exemple. http://www.youtube.com/watch?v=XcT4yYu_TTs

1 votes

Le Factory Pattern est injecté en tant que DI.

0 votes

Parfois, vous ne connaissez pas les caractéristiques de ICar à l'avance (comme des pneus spéciaux, en fonction de la météo). Dans ce cas, vous choisirez le point 2 et demanderez à ICarFactory de produire une voiture avec cet attribut. Beaucoup de DI sont faits parce qu'il n'y a pas de façon saine d'isoler vos composants avec des tests. #Les options 2 et 3 permettent de le faire.

0 votes

Il ne s'agit pas d'injection de dépendances, mais simplement de passer les dépendances. L'injection de dépendances n'a qu'une seule classe qui connaît les dépendances, ainsi l'appelant qui veut une RaceCar n'a pas besoin de savoir qu'il faut une voiture ou une carFactory. Cacher la dépendance (comme dans l'exemple 1) est le but de l'injection de dépendance. Elle n'est pas censée exposer les dépendances ; elle est censée garder le code qui les fournit à un seul endroit.

40voto

yfeldblum Points 42613

Certains problèmes faciles à résoudre avec l'injection de dépendances ne le sont pas aussi facilement avec une suite de fabriques.

La différence entre, d'une part, l'inversion de contrôle et l'injection de dépendances (IOC/DI), et, d'autre part, un localisateur de services ou une suite de fabriques (factory), est en partie :

IOC/DI est un écosystème complet d'objets et de services de domaine en soi. Il met tout en place pour vous de la manière que vous spécifiez. Les objets et services de votre domaine sont construits par le conteneur et ne se construisent pas eux-mêmes : ils n'ont donc pas d'obligation d'intégration. tout dépendances sur le conteneur ou sur les usines. IOC/DI permet un degré de configurabilité extrêmement élevé, toute la configuration se trouvant en un seul endroit (construction du conteneur) à la couche supérieure de votre application (l'interface graphique, le front-end Web).

Factory fait abstraction d'une partie de la construction des objets et services de votre domaine. Mais les objets et services du domaine doivent toujours trouver 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 où aller pour tout configurer.

22voto

Pup Points 3505

La gestion du cycle de vie est l'une des responsabilités que les conteneurs de dépendances assument 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 on l'appelle 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 de futures injections, comme les singletons ou les flyweights. Lorsqu'il est configuré pour créer de nouvelles instances de certains composants à chaque appel au conteneur, ce dernier oublie généralement l'objet créé.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X