J'ai lu sur le principe OCP et comment utiliser le modèle de stratégie pour y parvenir.
J'allais essayer d'expliquer cela à quelques personnes, mais le seul exemple auquel je puisse penser est l'utilisation de différentes classes de validation basées sur le statut d'une «commande».
J'ai lu quelques articles en ligne, mais ceux-ci ne décrivent généralement pas une vraie raison d'utiliser la stratégie, comme la génération de rapports / factures / validation, etc.
Y a-t-il des exemples concrets où vous pensez qu'un modèle de stratégie est courant?
la source
Cipher C =null; if (file.size() <= 2048) { C = new InMemoryCipherStrategy(); } else { c= SwaptToDiskCipher (); }
CipherFactory
peut dérouter ceux qui ne sont pas familiers avec le modèle de stratégie.Encore une fois, un ancien message apparaît toujours dans les recherches, je vais donc ajouter deux autres exemples (le code est en C #). J'adore le modèle de stratégie car il m'a souvent sauvé les fesses lorsque les chefs de projet disent: «Nous voulons que l'application fasse 'X', mais 'X' n'est pas encore clair et cela peut changer dans un proche avenir. " Cette vidéo expliquant le modèle de stratégie utilise StarCraft comme exemple.
Trucs qui entrent dans cette catégorie:
Tri: Nous voulons trier ces nombres, mais nous ne savons pas si nous allons utiliser BrickSort, BubbleSort ou un autre tri
Validation: Nous devons vérifier les éléments selon "Certaines règles", mais ce que sera cette règle n'est pas encore claire et nous pourrions en penser à de nouvelles.
Jeux: Nous voulons que le joueur marche ou coure quand il bouge, mais peut-être qu'à l'avenir, il devrait également être capable de nager, voler, se téléporter, creuser sous terre, etc.
Stockage des informations: nous voulons que l'application stocke les informations dans la base de données, mais plus tard, elle devra peut-être enregistrer un fichier ou effectuer un appel Web
Sortie: Nous devons générer X sous forme de chaîne simple, mais plus tard, il peut s'agir d'un CSV, XML, JSON, etc.
Exemples
J'ai un projet où les utilisateurs peuvent attribuer des produits à des personnes dans une base de données. Cette attribution d'un produit à une personne a un statut qui est "Approuvé" ou "Refusé", qui dépend de certaines règles métier. Par exemple: si un utilisateur attribue un produit à une personne d'un certain âge, son statut doit être refusé; Si la différence entre deux champs de l'élément est supérieure à 50, son statut est refusé, etc.
Aujourd'hui, au moment du développement, ces règles commerciales ne sont pas encore complètement claires et de nouvelles règles pourraient apparaître à tout moment. Le pouvoir du modèle stragety est que j'ai créé un RuleAgent, qui reçoit une liste d'IRules.
Au moment d'attribuer un produit à une personne, je crée un RuleAgent, je lui donne une liste de règles (qui implémentent toutes IRule) et lui demande de valider une affectation. Cela passera par toutes ses règles. Qui, parce qu'ils implémentent tous la même interface, ont tous la
IsApproved
méthode et retournent false si l'un d'eux retourne false.Maintenant, lorsque, par exemple, le gestionnaire arrive soudainement et dit, nous devons également refuser toutes les affectations à des stagiaires, ou toutes les affectations à des personnes qui font des heures supplémentaires ... Vous créez de nouveaux cours comme celui-ci:
Vous voyez que vous n'avez pas à continuer à ajouter ou à supprimer des instructions if ou du code, créez simplement une nouvelle classe de règles qui implémente l'interface IRUle et remplacez-les si nécessaire.
Un autre excellent exemple: la série de vidéos de Scott Allen sur http://www.asp.net/mvc/pluralsight où il utilise le modèle de stratégie dans la partie Test unitaire de l'application
Il crée un site Web qui a une page qui affiche des éléments en fonction de la popularité. Cependant, "Populaire" peut être composé de plusieurs éléments (la plupart des vues, la plupart des abonnés, la date de création, la plupart des activités, le moins de commentaires, etc.), et dans le cas où la gestion des cas ne sait pas encore exactement comment commander, et peut vouloir expérimenter différentes commandes à une date ultérieure. Vous créez une interface (IOrderAlgorithm ou quelque chose) avec une méthode de commande, et laissez un objet Orderer déléguer la commande à une implémentation concrète de l'interface IOrderAlgorithm. Vous pouvez créer un "CommentOrderer", "ActivityOrderer", etc ... Et les changer simplement lorsque de nouvelles exigences apparaissent.
la source
InternRule
maintenant mais comment déclenchons-nousOvertimeRule
? Comment pouvons-nous nous assurer que toute logique appeléeOvertimeRule.IsApproved
maintenant appelle égalementInternRule.IsApproved
?Notes clés:
La stratégie est un modèle de conception comportementale. Il est utilisé pour basculer entre les familles d'algorithmes.
Ce modèle contient une interface de stratégie abstraite et de nombreuses implémentations de stratégie concrète ( algorithmes ) de cette interface.
L'application utilise uniquement l' interface de stratégie . En fonction de certains paramètres de configuration, la stratégie concrète sera étiquetée à l' interface .
Diagramme UML de wikipedia
Un exemple concret : les compagnies aériennes offrent des réductions pendant certains mois (juillet-décembre) . Vous pouvez avoir un module Fare , qui décide des options de tarification en fonction du numéro du mois.
Jetez un œil à un exemple simple. Cet exemple peut être étendu aux applications de vente au détail en ligne, qui offrent facilement des rabais sur les articles du panier lors de jours spéciaux / happy hours.
production:
Articles utiles:
modèle de stratégie par dzone
modèle de stratégie par sourcemaking
la source
Je peux penser à plusieurs exemples assez simples:
Compression de données. Vous pourriez avoir une interface ICompressor dont la seule méthode ressemble à ceci:
byte [] compress (byte [] input);
Vos classes de compression concrètes peuvent être des choses comme RunLengthCompression, DeflateCompression, etc.
la source
Un usage courant du modèle de stratégie est de définir des stratégies de tri personnalisées (dans les langages sans fonctions d'ordre supérieur), par exemple pour trier une liste de chaînes par longueur en Java, en passant une classe interne anonyme (une implémentation de l'interface de stratégie):
De la même manière, des stratégies peuvent être utilisées pour des requêtes natives avec des bases de données d'objets, par exemple dans db4o:
la source
J'ai une application qui synchronise chaque jour sa base d'utilisateurs avec notre annuaire d'entreprise. Les utilisateurs sont éligibles ou non éligibles en fonction de leur statut dans l'Université. Chaque jour, le programme d'approvisionnement passe en revue et s'assure que ceux qui sont censés être éligibles sont approvisionnés dans l'application et ceux qui ne le sont pas sont déprovisionnés (en fait selon un algorithme de dégradation gracieuse, mais ce n'est pas la question). Samedi, je fais une mise à jour plus approfondie qui synchronise certaines propriétés de chaque utilisateur et m'assure qu'ils ont la bonne éligibilité. À la fin du mois, j'effectue un traitement de facturation en fonction de l'utilisation pour ce mois.
J'utilise un modèle de stratégie composable pour effectuer cette synchronisation. Le programme principal choisit essentiellement une stratégie de maître en fonction du jour de la semaine (synchroniser uniquement les changements / synchroniser tout) et l'heure du semestre par rapport au calendrier académique. Si le cycle de facturation se termine, il le compose également avec une stratégie de facturation. Il exécute ensuite la stratégie choisie via une interface standard.
Je ne sais pas à quel point c'est courant, mais j'avais l'impression que c'était un ajustement parfait pour le modèle de stratégie.
la source
Je sais que c'est une vieille question, mais je pense avoir un autre exemple intéressant que j'ai mis en œuvre récemment.
Ceci est un exemple très pratique du modèle de stratégie utilisé dans un système de livraison de documents.
J'avais un système de livraison PDF qui recevait une archive contenant beaucoup de documents et quelques métadonnées. Sur la base des métadonnées, il a décidé où placer le document; par exemple, selon les données, je pouvais stocker le document
A
,B
ou lesC
systèmes de stockage, ou un mélange des trois.Différents clients utilisaient ce système, et ils avaient des exigences différentes de gestion des annulations / erreurs en cas d'erreurs: on voulait que le système de livraison s'arrête à la première erreur, laisse tous les documents déjà livrés dans leurs stockages, mais arrête le processus et ne livre rien d'autre ; un autre voulait qu'il revienne en arrière
B
en cas d'erreurs lors du stockageC
, mais laisser tout ce qui était déjà livréA
. Il est facile d'imaginer qu'un troisième ou un quatrième aura également des besoins différents.Pour résoudre le problème, j'ai créé une classe de livraison de base qui contient la logique de livraison, ainsi que des méthodes pour restaurer des éléments de tous les stockages. Ces méthodes ne sont pas réellement appelées directement par le système de livraison en cas d'erreurs. Au lieu de cela, la classe utilise Dependency Injection pour recevoir une classe "Rollback / Error Handling Strategy" (basée sur le client utilisant le système), qui est appelée en cas d'erreurs, qui à son tour appelle les méthodes de rollback si cela est approprié pour cette stratégie.
La classe de livraison elle-même rapporte ce qui se passe dans la classe de stratégie (quels documents ont été livrés à quels stockages et quels échecs se sont produits), et chaque fois qu'une erreur se produit, elle demande à la stratégie si elle doit continuer ou non. Si la stratégie dit "arrêtez-le", la classe appelle la méthode "cleanUp" de la stratégie, qui utilise les informations précédemment rapportées pour décider quelles méthodes de restauration appeler à partir de la classe de livraison, ou simplement ne rien faire.
J'ai donc maintenant deux stratégies différentes: l'une est la
QuitterStrategy
(qui se ferme à la première erreur et ne nettoie rien) et l'autre est laMaximizeDeliveryToAStrategy
(qui essaie autant que possible de ne pas abandonner le processus et de ne jamais annuler les éléments livrés au stockageA
, mais annule des éléments deB
si la livraisonC
échoue).D'après ce que je comprends, c'est un exemple du modèle de stratégie. Si vous (oui, vous lisez) pensez que je me trompe, veuillez commenter ci-dessous et me le faire savoir. Je suis curieux de savoir ce qui constituerait une utilisation «pure» du modèle de stratégie et quels aspects de ma mise en œuvre enfreignent la définition. Je pense que cela a l'air un peu drôle car l'interface de stratégie est un peu grosse. Tous les exemples que j'ai vus jusqu'à présent n'utilisent qu'une seule méthode, mais je pense toujours que cela encapsule un algorithme (si un élément de logique métier peut être considéré comme un algorithme, ce que je pense que c'est le cas).
Étant donné que la stratégie est également notifiée des événements lors de l'exécution de la livraison, elle peut également être considérée comme un observateur , mais c'est une autre histoire.
Après avoir fait un peu de recherche, il semble que ce soit un "modèle composite" (comme MVC, un modèle qui utilise plusieurs modèles de conception en dessous d'une manière particulière) appelé le conseiller . C'est un conseiller pour savoir si la livraison doit se poursuivre ou non, mais c'est aussi un gestionnaire d'erreurs actif car il peut annuler des choses à la demande.
Quoi qu'il en soit, c'est un exemple assez complexe qui pourrait donner l'impression que les utilisations du modèle de stratégie sont trop simples / idiotes. Il peut être vraiment complexe et même plus applicable lorsqu'il est utilisé avec d'autres modèles.
la source
Le modèle de stratégie est le modèle le plus couramment utilisé, spécialement pour les validations et les algorithmes de tri.
Laissez-moi vous expliquer avec un exemple pratique simple
Le code de test pour cela est
Le même exemple est tiré de http://coder2design.com/strategy-pattern/
la source
Un bon exemple de modèle de stratégie serait dans un jeu où nous pouvons avoir différents personnages et chaque personnage peut avoir plusieurs armes à attaquer mais à la fois ne peut utiliser qu'une seule arme. Nous avons donc le personnage comme contexte, par exemple le roi, le commandant, le chevalier, le soldat et l'arme comme stratégie où l'attaque () pourrait être la méthode / l'algorithme qui dépend des armes utilisées. Donc, si les classes d'armes concrètes étaient Sword, Axe, Crossbow, BowAndArrow etc., elles implémenteraient toutes la méthode attack (). Je suis sûr que des explications supplémentaires ne sont pas nécessaires.
la source
J'ai utilisé l'approche stratégique dans un moteur assez complexe dans une application qui en est un bon exemple. Essentiellement, le rôle du moteur était d'aller chercher d'abord une liste de personnes qui avaient un widget, son deuxième rôle était de déterminer quelles étaient les 10 meilleures personnes avec un widget basé sur un nombre inconnu de paramètres (des choses comme la distance de prix des affaires précédentes ensemble , montant en stock, options d'expédition etc etc etc ...)
Essentiellement, nous avons divisé le problème en deux stratégies, la première étant la récupération de données, car nous savions que nous avions plusieurs sources de nos widgets et que nous devions être en mesure d'obtenir les données et de les transformer en une structure commune.
Nous avons également réalisé que nous avions plusieurs algorithmes, certains étaient basés sur la pondération des paramètres, d'autres étaient très bizarres et propices et je ne pouvais pas leur rendre justice sans sortir des visios et des graphiques et bien vous voyez l'image, nous avions beaucoup d'algorithmes pour sélectionner les meilleures personnes.
Notre service lui-même était très simple: il définissait essentiellement les entrées, les sorties et normalisait les données.Il utilisait également un modèle de fournisseur pour connecter les fournisseurs de données et les fournisseurs d'algorithmes spécifiques à l'application qui utilisaient la stratégie. C'était un système assez efficace.
Nous avons eu des débats si nous utilisions une stratégie ou un modèle de modèle que nous n'avons jamais résolu.
la source
Êtes-vous sûr que l'état d'une "commande" n'est pas un modèle d'état? J'ai le sentiment qu'une commande ne sera pas traitée différemment selon son statut.
Prenons par exemple la méthode Expédier à la Commande:
Le meilleur exemple du modèle d'état (et d'autres modèles) que j'ai trouvé était dans le livre " Head First Design Patterns ", ce qui est incroyable. La série de modèles de blogging de David Cumps sera une seconde proche .
la source
Supposons que vous souhaitiez écrire un algorithme pour calculer le nième Xday d'un mois et d'une année donnés, par exemple, le deuxième lundi d'octobre 2014. Vous souhaitez utiliser la classe Time d'Android
android.text.format.Time
pour représenter la date, mais vous souhaitez également écrire un algorithme générique cela peut également s'appliquer àjava.util.Calendar
.C'est ce que j'ai fait.
Dans DatetimeMath.java:
Dans TimeMath.java:
Dans OrdinalDayOfWeekCalculator.java, la classe avec l'algorithme générique:
Dans mon application Android, j'appellerais quelque chose comme
Si je veux réutiliser le même algorithme pour
java.util.Calendar
, j'écrirais simplement une classe CalendarMath qui implémente les trois méthodes dans DatetimeMath, puis j'utiliseraisla source
la source
Il y a quelques semaines, j'ai ajouté une interface Java commune qui a été implémentée par l'un de nos objets de domaine. Cet objet de domaine a été chargé à partir de la base de données et la représentation de la base de données était un schéma en étoile avec plus de 10 branches. L'une des conséquences d'avoir un objet de domaine aussi lourd est que nous avons dû créer d'autres objets de domaine qui représentaient le même schéma, bien que moins lourds. J'ai donc fait en sorte que les autres objets légers implémentent la même interface. En d'autres termes, nous avions:
À l'origine, je voulais utiliser
CollectibleElephant
pour trierElephant
s. Assez rapidement, mes coéquipiers se sont précipitésCollectibleElephant
pour exécuter des contrôles de sécurité, les filtrer au fur et à mesure qu'ils étaient envoyés à l'interface graphique, etc.la source
Nous avons dû créer une interface de provisioning tierce pour une plateforme d'entreprise avec une base de données très compliquée. La soumission des données à approvisionner était une liste de nos types de données qui ont été placés dans une file d'attente prioritaire dans notre application afin qu'ils puissent être écrits dans la base de données dans le bon ordre en raison des dépendances.
Le processus d'écriture de ces données était alors assez simple, continuez à apparaître en haut de la file d'attente prioritaire, puis choisissez une stratégie en fonction du type d'objet que vous extrayez.
la source
De wikipedia
Dans l'application Windows Paint, vous pouvez voir un modèle de stratégie dans lequel vous pouvez choisir la forme et la couleur indépendamment dans différentes sections. Ici, la forme et la couleur sont les algorithmes qui peuvent être modifiés à l'exécution.
Si vous souhaitez dessiner un cercle de couleur rouge, plutôt que de fournir une option de «RedCircle», ils vous permettent de choisir le cercle et une couleur de votre choix.
Sans modèle de stratégie, le nombre de classes augmentera avec le produit cartésien de la forme et de la couleur. L'interface change également pour chaque implémentation.
la source
Imaginez un jeu de tir avec des ennemis IA par exemple. Vous voulez qu'ils se battent continuellement de différentes manières en fonction de ce qui se passe. Avec le modèle de stratégie, vous pouvez continuellement boucler et changer dynamiquement la façon dont une action ou une action spécifique sera effectuée.
la source