Le modèle de stratégie et l'injection de dépendance nous permettent tous les deux de définir/injecter des objets au moment de l'exécution. Quelle est la différence entre le modèle de stratégie et l'injection de dépendance?
DI et Strategy fonctionnent de la même manière, mais Strategy est utilisé pour les dépendances plus fines et de courte durée.
Lorsqu'un objet est configuré avec une stratégie "fixe", par exemple lorsque l'objet est construit, la distinction entre stratégie et DI s'estompe. Mais dans un scénario DI, il est plus inhabituel que les dépendances des objets changent au cours de leur vie, ce qui n’est pas rare avec Strategy.
En outre, vous pouvez passer des stratégies en tant qu'arguments à des méthodes, alors que le concept associé d'injection d'argument de méthode n'est pas répandu et est principalement utilisé dans le contexte de tests automatisés uniquement.
La stratégie se concentre sur l'intention et vous encourage à créer une interface avec différentes implémentations qui obéissent au même contrat comportemental. DI consiste plus simplement à mettre en œuvre un comportement et à le fournir.
Avec DI, vous pouvez décomposer votre programme pour des raisons autres que le simple fait d’échanger des parties de l’implémentation. Une interface utilisée dans DI avec une seule implémentation est très courante. Une "stratégie" avec une seule mise en œuvre concrète (jamais) n'est pas un problème réel mais est probablement plus proche de DI.
La différence est ce qu'ils essaient de réaliser. Le modèle de stratégie est utilisé dans des situations où vous savez que vous souhaitez échanger des implémentations. Par exemple, vous pouvez formater les données de différentes manières - vous pouvez utiliser le modèle de stratégie pour échanger un formateur XML ou CSV, etc.
L'injection de dépendance est différente en ce que l'utilisateur n'essaie pas de changer le comportement à l'exécution. Suivant l'exemple ci-dessus, nous pourrions créer un programme d'exportation XML utilisant un formateur XML. Plutôt que de structurer le code comme ceci:
public class DataExporter() {
XMLFormatter formatter = new XMLFormatter();
}
vous «injecteriez» le formateur dans le constructeur:
public class DataExporter {
IFormatter formatter = null;
public DataExporter(IDataFormatter dataFormatter) {
this.formatter = dataFormatter;
}
}
DataExporter exporter = new DataExporter(new XMLFormatter());
Il existe quelques justifications pour l’injection de dépendance, mais la principale est de tester. Vous pouvez avoir un cas où vous avez un moteur de persistance (tel qu'une base de données). Toutefois, il peut être difficile d’utiliser une vraie base de données lorsque vous exécutez des tests à plusieurs reprises. Ainsi, pour vos cas de test, vous devez injecter une base de données fictive, afin d'éviter les frais généraux.
En utilisant cet exemple, vous pouvez voir la différence: nous prévoyons toujours d'utiliser une stratégie de stockage de données, et c'est celle que nous transmettons (l'instance de base de données réelle). Cependant, en développement et en test, nous souhaitons utiliser différentes dépendances, nous injectons donc différentes concrétions.
Vous pouvez utiliser DI en tant que modèle de stratégie pour basculer dans l'algorithme requis pour chaque client. Toutefois, DI peut aller au-delà, car il s'agit d'un moyen de découpler les parties d'une application, ce qui ne ferait pas partie intégrante de l'application. le modèle de stratégie.
Il serait risqué de dire que l’ID est juste un schéma stratégique renommé, car cela commence à diluer son objectif, l’OMI.
Mec, l'injection de dépendance est un schéma plus général, et il s'agit d'une dépendance à des abstractions et non à des concrétions; cela fait partie de chaque schéma, mais le schéma Stratégie est une solution à un problème plus spécifique.
c'est la définition de wikipedia:
DI:
Injection de dépendance (DI) in programmation informatique orientée objet est un motif de conception avec un noyau principe de séparation du comportement de résolution de dépendance. En d'autres termes: une technique pour découpler fortement composants logiciels dépendants.
Modèle de stratégie:
En programmation informatique, la stratégie pattern (également connu sous le nom de stratégie pattern) est un logiciel particulier modèle de conception, grâce auquel les algorithmes peuvent être sélectionné au moment de l'exécution.
Le modèle de stratégie est destiné à fournir un moyen de définir une famille de algorithmes, encapsuler chacun comme un objet, et les rendre interchangeables . Le modèle de stratégie laisse le les algorithmes varient indépendamment de les clients qui les utilisent.
Les stratégies sont des choses de plus haut niveau utilisées pour changer la façon dont les choses sont calculées. Avec l'injection de dépendance, vous pouvez non seulement changer la façon dont les choses sont calculées, mais aussi changer ce qui existe.
Pour moi, cela devient clair lors de l'utilisation de tests unitaires. Pour l’exécution du code de production, vous avez toutes les données cachées (privées ou protégées); alors qu'avec les tests unitaires, la plupart des données sont publiques, je peux donc les examiner avec les assertions.
Exemple de stratégie:
public class Cosine {
private CalcStrategy strat;
// Constructor - strategy passed in as a type of DI
public Cosine(CalcStrategy s) {
strat = s;
}
}
public abstract class CalcStrategy {
public double goFigure(double angle);
}
public class RadianStrategy extends CalcStrategy {
public double goFigure(double angle) {
return (...);
}
}
public class DegreeStrategy extends CalcStrategy {
public double goFigure(double angle) {
return (...);
}
}
Notez qu’il n’existe aucune donnée publique différente entre les stratégies. Il n'y a pas non plus de méthodes différentes. Les deux stratégies partagent toutes les mêmes fonctions et signatures.
Maintenant pour l'injection de dépendance:
public class Cosine {
private Calc strat;
// Constructor - Dependency Injection.
public Cosine(Calc s) {
strat = s;
}
}
public class Calc {
private int numPasses = 0;
private double total = 0;
private double intermediate = 0;
public double goFigure(double angle) {
return(...);
}
public class CalcTestDouble extends Calc {
// NOTICE THE PUBLIC DATA.
public int numPasses = 0;
public double total = 0;
public double intermediate = 0;
public double goFigure(double angle) {
return (...);
}
}
Utilisation:
public CosineTest {
@Test
public void testGoFigure() {
// Setup
CalcTestDouble calc = new CalcTestDouble();
Cosine instance = new Cosine(calc);
// Exercise
double actualAnswer = instance.goFigure(0.0);
// Verify
double tolerance = ...;
double expectedAnswer = ...;
assertEquals("GoFigure didn't work!", expectedAnswer,
actualAnswer, tolerance);
int expectedNumPasses = ...;
assertEquals("GoFigure had wrong number passes!",
expectedNumPasses, calc.numPasses);
double expectedIntermediate = ...;
assertEquals("GoFigure had wrong intermediate values!",
expectedIntermediate, calc.intermediate, tolerance);
}
}
Notez les 2 derniers chèques. Ils ont utilisé les données publiques dans le test double qui a été injecté dans la classe sous test. Je ne pouvais pas faire cela avec le code de production à cause du principe de dissimulation des données. Je ne voulais pas que le code de test à usage spécifique soit inséré dans le code de production. Les données publiques devaient appartenir à une classe différente.
Le double de test a été injecté. C’est différent de la stratégie car elle touche les données et pas seulement les fonctions.
L'injection de dépendance est un raffinement du modèle de stratégie que je vais expliquer brièvement. Il est souvent nécessaire de choisir entre plusieurs modules alternatifs au moment de l'exécution. Ces modules implémentent tous une interface commune afin de pouvoir être utilisés de manière interchangeable. Le modèle de stratégie a pour but de supprimer le fardeau de choisir lequel des modules utiliser (c.-à-d. Quelle "stratégie concrète" ou dépendance) en encapsulant le processus de prise de décision dans un objet séparé que j'appellerai l'objet stratégie.
L'injection de dépendance affine le modèle de stratégie en décidant non seulement quelle stratégie concrète utiliser, mais en créant une instance de la stratégie concrète et en la "réinjectant" dans le module appelant. Ceci est utile même s'il n'y a qu'une seule dépendance, car la connaissance de la gestion (initialisation, etc.) de l'instance de stratégie concrète peut également être masquée dans l'objet de stratégie.
En fait, l’injection de dépendance est également très similaire au modèle Bridge. Pour moi (et selon la définition), le modèle Bridge doit prendre en charge différentes versions de la mise en œuvre, tandis que le modèle Stratégie concerne une logique totalement différente. Mais l'exemple de code ressemble à l'utilisation de DI. Alors peut-être que DI est juste une technique ou une implémentation?
La stratégie est un moyen d’utiliser vos compétences en matière d’injection de dépendance. Les moyens concrets de mettre en œuvre l’injection de dépendance sont les suivants: -
Il y a cependant une chose qui distingue la stratégie. Comme vous le savez dans Unity au démarrage de l'application, toutes les dépendances sont définies et nous ne pouvons plus les modifier. Mais la stratégie prend en charge le changement de dépendance à l'exécution. Mais WE devons gérer/injecter la dépendance, pas la responsabilité de la stratégie!
En réalité, la stratégie ne parle pas d'injection de dépendance. Si nécessaire, vous pouvez le faire via Abstract Factory dans un modèle de stratégie. Stratégie ne parle que de créer une famille de classes avec interface et de "jouer" avec elle. En jouant, si nous trouvons les classes dans un niveau différent, nous devons l’injecter nous-mêmes mais pas le travail de Strategy.
Si nous considérons les principes SOLID, nous utilisons le modèle de stratégie pour le principe ouvert fermé et le principe d'injection de dépendance pour l'inversion de dépendance