Les deux modèles de conception encapsulent un algorithme et découplent les détails d’implémentation de leurs classes d’appel. La seule différence que je peux discerner est que le modèle de stratégie prend des parameters pour l’exécution, alors que le modèle de commande ne le fait pas.
Il me semble que le modèle de commande nécessite que toutes les informations d’exécution soient disponibles lors de sa création et qu’il puisse retarder son appel (peut-être dans le cadre d’un script).
Quelles déterminations guident l’utilisation ou non d’un modèle?
J’inclus une table de hiérarchie d’encapsulation de plusieurs modèles de conception GoF pour aider à expliquer les différences entre ces deux modèles. Espérons que cela illustre mieux ce que chacun encapsule, donc mon explication a plus de sens.
Tout d’abord, la hiérarchie répertorie l’étendue pour laquelle un modèle donné est applicable ou le modèle approprié à utiliser pour encapsuler un certain niveau de détail, selon le côté de la table où vous commencez.
Comme vous pouvez le voir dans le tableau, un object Strategy Pattern masque les détails de l’implémentation d’un algorithme. L’utilisation d’un object de stratégie différent remplit les mêmes fonctionnalités, mais de manière différente. Chaque object de stratégie peut être optimisé pour un facteur particulier ou opérer sur un autre paramètre; et, grâce à l’utilisation d’une interface commune, le contexte peut fonctionner sans problème non plus.
Le modèle de commande encapsule un niveau de détail beaucoup plus petit qu’un algorithme. Il encode les détails nécessaires pour envoyer un message à un object: récepteur, sélecteur et arguments. L’avantage d’objectiver une si petite partie de l’exécution du processus est que de tels messages peuvent être invoqués de manière générale à différents moments ou endroits sans avoir à coder en dur ses détails. Il permet d’appeler les messages une ou plusieurs fois ou de les transmettre à différentes parties du système ou à plusieurs systèmes sans que les détails d’un appel spécifique soient connus avant leur exécution.
Comme c’est généralement le cas pour les motifs de conception, ils ne nécessitent pas que toutes les implémentations soient identiques en détail pour porter le nom du motif. Les détails peuvent varier dans l’implémentation et dans les données encodées dans l’object par rapport aux arguments de la méthode.
Les stratégies encapsulent des algorithmes. Les commandes séparent l’expéditeur du destinataire d’une requête, elles transforment une requête en object.
Si c’est un algorithme, comment quelque chose sera fait, utilisez une stratégie. Si vous devez séparer l’appel d’une méthode de son exécution, utilisez une commande. Les commandes sont souvent utilisées lorsque vous mettez en queue des messages pour une utilisation ultérieure, comme une tâche ou une transaction.
Répondre à une très vieille question. (Est-ce que quelqu’un voit les dernières réponses au lieu des plus votées?)
C’est une confusion valable à avoir à cause des similitudes. Les schémas de stratégie et de commande utilisent tous deux l’ encapsulation . Mais cela ne les rend pas identiques.
La principale différence est de comprendre ce qui est encapsulé. Le principe OO, dont les deux modèles dépendent, est Encapsuler ce qui varie .
En cas de stratégie, l’ algorithme est différent. Par exemple, un object de stratégie sait comment générer un fichier XML, tandis que l’autre produit un fichier JSON. Différents algorithmes sont conservés ( encapsulés ) dans différentes classes. C’est aussi simple que ça.
En cas de commande, la demande elle-même varie. La demande peut provenir du File Menu > Delete
ou Right Click > Context Menu > Delete
Just Delete Button pressed
Right Click > Context Menu > Delete
ou Just Delete Button pressed
. Les trois cas peuvent générer 3 objects de commande du même type. Ces objects de commande ne représentent que 3 demandes de suppression; algorithme de suppression Puisque les requêtes sont des tas d’objects, nous pouvons les gérer facilement. Soudain, il devient sortingvial de fournir des fonctionnalités telles que défaire ou rétablir.
Peu importe comment la commande implémente la logique demandée. En appelant execute (), il peut implémenter un algorithme pour déclencher la suppression ou même le déléguer à d’autres objects, voire déléguer à une stratégie. Ce n’est que le détail de l’implémentation du modèle de commande. C’est pourquoi il est nommé comme commande bien que ce ne soit pas une manière polie de demander : -)
Contraste avec la stratégie; ce modèle ne concerne que la logique réelle qui est exécutée. Si nous faisons cela, cela aide à obtenir différentes combinaisons de comportements avec un ensemble minimal de classes, empêchant ainsi une explosion de classes.
Je pense que Command nous aide à élargir notre compréhension de l’encapsulation, alors que la stratégie fournit une utilisation naturelle de l’encapsulation et du polymorphism.
La façon dont je le vois est que vous avez plusieurs façons de faire la même chose, chacune d’elles étant une stratégie, et lors de l’exécution, quelque chose détermine quelle stratégie est exécutée.
Essayez d’abord StrategyOne, si les résultats ne sont pas assez bons, essayez StrategyTwo …
Les commandes sont liées à des choses distinctes qui doivent se produire comme TryToWalkAcrossTheRoomCommand. Cette commande sera déclenchée à chaque fois qu’un object essaiera de traverser la pièce, mais à l’intérieur, il pourrait essayer StrategyOne et StrategyTwo pour avoir tenté de traverser la pièce.
marque
Je peux me tromper, mais je considère la commande comme une fonction à exécuter ou une réaction. Il devrait y avoir au moins deux joueurs: celui qui demande l’action et celui qui exécute l’action. L’interface graphique est un exemple typique de modèle de commande:
La commande est généralement limitée à un domaine ou à un domaine d’activité, mais n’est pas nécessaire: vous pouvez avoir des commandes émettant une facture, démarrant une fusée ou supprimant un fichier implémentant la même interface (par exemple, méthode simple execute()
. Souvent, les commandes sont autonomes, donc elles n’ont pas besoin de l’exécuteur pour traiter la tâche à laquelle elles sont destinées (toutes les informations nécessaires sont fournies au moment de la construction), parfois les commandes sont sensibles au contexte et devraient pouvoir découvrir ce contexte. (La commande Backspace doit connaître la position du curseur dans le texte pour supprimer correctement le caractère précédent; la commande Rollback doit détecter la transaction en cours à annuler; …).
La stratégie est un peu différente: elle est plus liée à certains domaines. La stratégie peut définir une règle pour formater une date (en UTC? Locale spécifique?) (Stratégie “formateur de date”) ou pour calculer un carré pour une figure géomésortingque (stratégie “calculateur carré”). Les stratégies sont en ce sens des objects de poids mouche, qui prennent quelque chose comme entrée (“date”, “figure”, …) et prennent des décisions sur leur base. Peut-être pas le meilleur, mais le bon exemple de stratégie est celui lié à l’interface javax.xml.transform.Source
: selon que l’object passé est DOMSource
ou SAXSource
ou StreamSource
la stratégie (= transformateur XSLT dans ce cas) appliquera différentes règles à traiter. La mise en œuvre peut être un simple switch
ou impliquer un modèle de chaîne de responsabilité .
Mais en effet, il y a quelque chose en commun entre ces deux modèles: les commandes et les stratégies encapsulent des algorithmes dans la même zone sémantique.
Commander:
Composants de base:
execute()
Workflow:
Le client appelle Invoker => Invoker appelle ConcreteCommand => appels ConcreteCommand La méthode Receiver , qui implémente la méthode de commande abstraite.
Avantage : le client n’est pas affecté par les modifications apscopes à la commande et au récepteur. Invoker fournit un couplage libre entre le client et le récepteur. Vous pouvez exécuter plusieurs commandes avec le même invocateur.
Le modèle de commande vous permet d’exécuter une commande sur différents récepteurs en utilisant le même invocateur . Invoker ignore le type de récepteur
Pour une meilleure compréhension des concepts, consultez cet article de JournalDev de Pankaj Kumar et l’ article de dzone de James Sugrue en plus du lien Wikipedia.
Vous pouvez utiliser le modèle de commande pour
Découple l’invocateur et le receveur de commande
Implémenter le mécanisme de rappel
Implémenter les fonctionnalités d’annulation et de restauration
Maintenir un historique des commandes
java.lang.Thread
est une bonne implémentation du modèle de commande . Vous pouvez traiter Thread comme invocateur et classe implémentant la méthode Runnable comme ConcreteCommonad / Receiver et run()
tant que commande .
La version Undo / Redo du modèle de commande peut être lue dans l’ article de Theodore Norvell
Stratégie:
Le schéma de stratégie est très simple à comprendre. Utilisez ce modèle lorsque
Vous avez plusieurs implémentations pour un algorithme et l’implémentation de l’algorithme peut changer au moment de l’exécution en fonction de conditions particulières .
Prenons un exemple de la composante tarifaire du système de réservation des compagnies aériennes
Les compagnies aériennes souhaiteraient proposer différents tarifs au cours de différentes périodes – les périodes de pointe et hors pointe. En période de pointe, il souhaite stimuler la demande en proposant des remises attractives.
Points clés de la stratégie :
Articles connexes avec des exemples de code:
Utilisation du modèle de conception de commandes
Real World Exemple de modèle de stratégie
Pour moi, la différence est une intention. Les implémentations des deux modèles sont assez similaires, mais ont des objectives différents:
Pour une stratégie, le composant utilisant l’object sait ce que fait l’object (et l’utilisera pour effectuer une partie de son propre travail), mais il ne se soucie pas de la manière dont il le fait.
Pour une commande, le composant utilisant l’object ne sait ni ce que fait la commande ni comment il le fait – il sait simplement comment l’invoquer. La tâche de l’appelant consiste simplement à exécuter la commande – le traitement effectué par la commande ne fait pas partie du travail principal de l’appelant.
C’est la différence – l’object utilisant le composant sait-il réellement ce que le composant fait? La plupart du temps, cela peut être déterminé selon que l’object modèle renvoie une valeur à son invocateur. Si l’invocateur se soucie de ce que fait l’object pattern, il voudra probablement qu’il retourne quelque chose et ce sera une stratégie. S’il ne se soucie d’aucune valeur de retour, il s’agit probablement d’une commande (notez que quelque chose comme Java Callable est toujours une commande car, bien qu’il renvoie une valeur, l’appelant ne se soucie pas de la valeur). à ce qui a fourni à l’origine le commandement).