Je suis nouveau pour concevoir des modèles et travailler à travers la méthode d'usine et les modèles de stratégie. Je comprends que cette usine est un modèle et une stratégie de création est un comportement, mais j'ai du mal à comprendre quand utiliser lequel. Par exemple, j'ai les classes suivantes qui mettent à jour les détails du client en fonction de la société spécifiée:
public interface IUpdateDetails { void UpdateDetails(); }
public class UPSUpdateDetails : IUpdateDetails
{
public void UpdateDetails() => Console.WriteLine("Call web service to update details for UPS...");
}
public class FedExUpdateDetails : IUpdateDetails
{
public void UpdateDetails() => Console.WriteLine("Update database for FedEx...");
}
public class DHLUpdateDetails : IUpdateDetails
{
public void UpdateDetails() => Console.WriteLine("Send Email for DHL...");
}
Je peux créer une usine pour renvoyer la classe correcte:
public class UpdateDetailsFactory
{
public static IUpdateDetails Create(string type)
{
switch (type)
{
case "UPS":
return new UPSUpdateDetails();
case "DHL":
return new DHLUpdateDetails();
case "FedEx":
return new FedExUpdateDetails();
default:
throw new ArgumentException();
}
}
}
et mettez-le comme suit:
// Using Factory
string company = "UPS"; // Get company from database
IUpdateDetails updateDetails = UpdateDetailsFactory.Create(company);
updateDetails.UpdateDetails();
Console.ReadLine();
ou je peux utiliser le modèle de stratégie:
public class UpdateDetailsContext
{
private IUpdateDetails strategy;
public void SetStrategy(IUpdateDetails updateDetails) => strategy = updateDetails;
public void Update() => strategy.UpdateDetails();
}
et mettez-le comme suit:
// Using Strategy
UpdateDetailsContext context = new UpdateDetailsContext();
context.SetStrategy(UpdateDetailsFactory.Create(company));
context.Update();
Console.ReadLine();
Ma question est - je comprends-moi correctement les modèles? Quelle est la différence entre l'utilisation de celle de l'autre?
Vous êtes correct que ceux-ci ont beaucoup de similitudes. Comme mentionné dans d'autres réponses, la différence concerne les objectifs.
Le modèle de stratégie est souvent mal compris, mais c'est aussi l'un d'entre eux des modèles les plus précieux pour simplifier le code. La clé du modèle est qu'il vous permet d'avoir des objets qui changent de comportement au moment de l'exécution. Pour en penser un bon exemple, considérez un jeu vidéo où vous êtes dans une bataille avec un ennemi non-joueur. À un moment donné, lorsque vous avez réduit la "santé" de l'ennemi à un certain niveau, l'ennemi passera d'un "combat" à un mode "vol". Maintenant, vous pourriez mettre un bazillion si des déclarations partout à la place pour vérifier quel mode il est mais c'est un énorme gâchis. Au lieu de cela, vous utilisez un modèle de stratégie et disposez d'un ensemble de définitions de comportement différents représentés comme des objets. Selon le niveau "Santé", le comportement correct est utilisé.
Cela ne s'applique pas uniquement aux jeux vidéo. Disons que vous disposiez d'un système de commande et que vous avez reçu des exigences pour revenir à un fournisseur de cloud secondaire (plus cher mais plus fiable, disons.) Vous pouvez utiliser le modèle de stratégie pour garder cette sain d'esprit.
Le modèle de méthode d'usine est un bon remplacement pour un constructeur. Un excellent exemple de ceci est une chose comme une usine entière qui retourne le même objet à chaque fois que vous passez dans la valeur 0 ou 1.
La chose est que vous pouvez réellement les mettre ensemble de nombreuses manières intéressantes. Par exemple, vous pouvez créer une méthode d'usine utilisant un modèle de stratégie pour déterminer les objets à créer. Par exemple, vous pouvez l'utiliser dans l'exemple de système de commande ci-dessus pour renvoyer des objets de connexion DB différents en fonction des circonstances.
Une scie commune est "des motifs sont descriptifs, non normatifs". En d'autres termes, ce sont des moyens de décrire une approche de conception, pas des recettes. Une erreur commune essaie de les utiliser comme des Legos pour construire une solution.
Ma question est - je comprends-moi correctement les modèles?
Principalement. Votre implémentation d'usine, bien que correcte, est un peu étrange car la seule différence est UpdateDetails
. Ce genre de chose serait mieux fait comme une stratégie (une simple lambda en C #). En pratique, les usines ont tendance à varier leurs implémentations concrètes un peu plus - faire la différence dans les modèles plus clairs.
Quelle est la différence entre l'utilisation de celle de l'autre?
En général, une stratégie est utilisée par autres objets. Vous leur donnez la stratégie et ils le font sans savoir nécessairement ce qu'il fait. Vous les utilisez lorsque vous souhaitez rendre votre comportement flexible.
Une usine fournit vous avec un objet inconnu basé sur des entrées d'exécution. Vous les utilisez lorsque vous souhaitez modifier votre résultat au moment de l'exécution. Habituellement, vous avez un ensemble fixe de choses que l'usine peut construire. Vous ne cherchez pas une flexibilité autant que vous souhaitez abstraire la création conditionnelle.
Et rappelez-vous que les motifs sont principalement pour communication. Même si vous pouvez accomplir les mêmes choses avec une stratégie et une structure d'usine, elles impliquent différentes choses lorsque vous communiquez avec d'autres développeurs. L'usine est clairement "je crée des choses" où une stratégie est légèrement moins clairement ", je vous permet de spécifier un comportement".
Lorsque vous avez plus d'un modèle qui correspond à un problème bien, les principales différences entre les modèles correspondent à la manière dont vous envisagez de les consommer. Souvent, les motifs ne vivent pas isolément et sont utilisés avec d'autres principes de conception qui influent sur la question de savoir si l'autre est plus préférable à l'autre.
Par exemple, le modèle d'usine que vous avez défini est parfaitement bien pour vous assurer que la version correcte de la mise en œuvre IUpdateDetails
. Les applications à base d'injection de dépendance implémentent généralement l'usine pour vous afin de pouvoir filmer automatiquement la bonne implémentation lorsque vous devez réellement le consommer. Il y a des cas où vous auriez réellement besoin d'avoir l'usine que vous l'avez également définie.
Lorsque le cas d'utilisation est simple (comme dans votre exemple fourni), il n'y a aucun avantage du modèle de stratégie. C'est juste un peu plus de travail sans avantage supplémentaire. Cependant, si nous devions développer l'exemple beaucoup plus, nous verrions que c'est une valeur un peu plus.
Commençons maintenant de faire la finition:
class ShippingContext
{
private IUpdateDetails updateDetails;
private IQueryHistory queryHistory;
private string trackingNumber;
private string currentLocation;
public ShippingContext(string trackingNumber)
{
this.trackingNumber = trackingNumber;
var company = ShippingFactory.DetectCompany(trackingNumber);
queryHistory = ShippingFactory.CreateHistoryTracker(company);
updateDetails = ShippingFactory.CreateDetailsUpdater(company);
}
public TrackingHistory RetrieveHistory()
{
var history = queryHistory.Retrieve(trackingNumber);
lastLocation = history.Current.Location;
return history;
}
public void UpdateDetails()
{
updateDetails.Update(trackingNumber, lastLocation);
}
}
Dans ce cas, nous nous cachons tous les détails des différentes classes que nous utilisons et comment les coordonner. Tout ce qui est exposé est le fait que nous faisons le même travail contre un numéro de suivi connu.
var context = new ShippingContext("1Z9999999999999999");
var history = context.RetrieveHistory();
// do some extra things with history, or display it on screen
context.UpdateDetails();
Console.ReadLine();
La chose que le modèle de stratégie fournit est le processus étape par étape sur la manière d'interagir avec les choses. Les détails quant à ce qui doit se produire en vertu des couvertures est pris en charge au nom de l'utilisateur.
suis-je comprendre les modèles correctement?
Oui. Je dirais que vos implémentations look théoriquement parfaite.
Quelle est la différence entre l'utilisation de celle de l'autre?
Vous pourriez aussi bien dire personne ...
Laissez-moi vous dire un secret ":
En conséquence, votre code devrait être un récit de ce que vous avez dans votre esprit. Les Détails techniques seront écrits, éventuellement, mais ils seront cachés aussi profondément que possible.
Quoi que vous puissiez faire avec le modèle de stratégie, vous pouvez également faire avec le modèle d'usine également (et de nombreux autres modèles). Votre choix devrait être guidé par la règle de base suivante:
Et par "moins bizarre", je veux dire, bien sûr, tout ce qui correspond le mieux à votre réalité modélisée (c'est-à-dire votre récit). Nous choisissons d'écrire du code de la manière la plus expressive possible car c'est comme ça que nous le comprenons mieux. Voici comment les motifs ont émergé ... en traduisant des idées du monde réel au code. Par conséquent, leur façon de choisir entre les modèles est de penser à laquelle on pourrait Express votre problème plus intuitivement.
Alors ... UpdateDetails
est une classe (OK, cachée derrière une interface). Il représente un objet. Quelle est la signification d'un tel objet? La façon dont je le lis, cela me rappelle plus d'une action qu'un objet, dans un récit de langue naturelle (car c'est un verbe). Je suis déjà confondu de votre représentation d'une action en tant qu'objet, donc une usine ne complique que les choses plus loin. Cela signifie que si vous utilisez une usine, vous n'êtes plus clair dans votre narration.
Par conséquent, pour répondre à votre question plus directement, vous utilisez une usine lorsque:
Vous utilisez une stratégie lorsque:
Tout cela, pas à cause de la règle "élevée", mais parce que vous faites votre code un "récit" d'une situation réelle de la vie réelle, de sorte que plus de gens seront en mesure de l'interpréter (y compris votre avenir futur, quand vous récupérez à votre propre code et essayez de vous rappeler ce que vous aviez l'intention de faire), augmentant ainsi son expressivité!
Le modèle d'usine est destiné à être utilisé lors de la création d'instances de types qui implémentent une interface d'intérêt spécifique (c'est-à-dire lors de la création de quelque chose qui implémente l'interface dont vous avez besoin). Le modèle d'usine cache tous les détails inutiles de la manière dont la mise en œuvre de l'interface a été créée, permettant donc d'être modifiée ultérieurement au besoin sans (ou presque sans) affecter le reste du code qui utilise réellement la mise en œuvre de l'interface. L'usine réelle pourrait être sans paramétrage ou paramétré selon que la logique de création de la mise en œuvre de l'interface nécessite des "astuces" sur la manière de créer exactement l'instance de mise en œuvre.
Le modèle de stratégie est destiné à permettre une alternance facile d'une mise en œuvre attendue d'action/opération si nécessaire. Chaque alternative est mise en œuvre par différents types de stratégies pertinentes mettant en œuvre l'action/fonctionnement similaire ". D'autre part, une implémentation d'usine suppose généralement que la même usine peut produire des implémentations alternatives de l'interface attendue/demandée (basée sur certaines conditions, paramètres, pré-configuration).
Les deux modèles peuvent être utilisés ensemble dans des scénarios plus complexes où, par exemple, une usine utilise une collection de stratégies interne afin de déléguer la construction réelle de l'objet de mise en œuvre de l'interface attendue à une stratégie spécifique après que l'usine a pris une décision avec stratégie. utilisé. Mais cette façon, l'appelée de l'usine n'a aucune idée du fait que les stratégies sont invoquées derrière la scène.