121 votes

Utilisation d'un modèle de stratégie et d'un modèle de commande

Les deux patrons de conception encapsulent un algorithme et découplent les détails de mise en œuvre de leurs classes d'appel. La seule différence que je peux discerner est que le modèle Strategy prend des paramètres pour l'exécution, alors que le modèle Command ne le fait pas.

Il me semble que le patron de commande nécessite que toutes les informations pour l'exécution soient disponibles lors de sa création, et qu'il est capable de retarder son appel (peut-être dans le cadre d'un script).

Quelles sont les déterminations qui guident l'utilisation d'un modèle ou d'un autre ?

95voto

Huperniketes Points 696

J'ai inclus un tableau de hiérarchie d'encapsulation de plusieurs des modèles de conception GoF pour aider à expliquer les différences entre ces deux modèles. J'espère qu'il illustre mieux ce que chacun encapsule et que mon explication aura plus de sens.

Tout d'abord, la hiérarchie énumère le champ d'application d'un modèle donné, ou le modèle approprié à utiliser pour encapsuler un certain niveau de détail, selon le côté du tableau où vous commencez.

design pattern encapsulation hierarchy table

Comme vous pouvez le voir dans le tableau, un objet Strategy Pattern cache les détails de l'implémentation d'un algorithme. Ainsi, l'utilisation d'un objet strategy différent permettra d'exécuter la même fonctionnalité mais d'une manière différente. Chaque objet de stratégie peut être optimisé pour un facteur particulier ou fonctionner sur un autre paramètre ; grâce à l'utilisation d'une interface commune, le contexte peut travailler en toute sécurité avec l'un ou l'autre.

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 objet : récepteur, sélecteur et arguments. L'avantage d'objectiver une partie aussi infime de l'exécution d'un processus est que de tels messages peuvent être invoqués à différents moments ou endroits de manière générale sans avoir à coder en dur les détails. Les messages peuvent être invoqués une ou plusieurs fois, ou transmis à différentes parties du système ou à plusieurs systèmes sans que les détails d'une invocation spécifique soient connus avant l'exécution.

Comme c'est le cas pour les patrons de conception, il n'est pas nécessaire que toutes les implémentations soient identiques dans les détails pour porter le nom du patron. Les détails peuvent varier dans l'implémentation et dans les données encodées dans l'objet ou dans les arguments de méthode.

0 votes

Donc, si j'avais un système qui filtrait les résultats avec un "pipeline de filtres" et utilisait des délégués comme filtres (où chacun des algorithmes du filtre serait encapsulé dans une fonction), cela serait-il considéré comme un modèle de commande ? Dans ce cas, je vois le délégué de la fonction de filtrage comme fournissant une sorte de contrat pour ce que chaque filtre doit respecter en termes d'entrée et de sortie.

4 votes

@KTF, non. Le pattern Command utilise un objet qui possède la plupart (si ce n'est toutes) les informations nécessaires (par exemple, le récepteur, le sélecteur, les arguments) pour invoquer la méthode d'un objet. C'est un modèle simpliste qui peut être utilisé dans d'autres modèles de conception tels que la chaîne de responsabilité, la collection et le modèle Pipeline que vous décrivez. Le "contrat en quelque sorte" fourni par vos délégués est un autre modèle, l'interface.

51voto

Paul Rubel Points 13132

Les stratégies encapsulent les algorithmes. Les commandes séparent l'émetteur du récepteur d'une demande, elles transforment une demande en objet.

S'il s'agit d'un algorithme, de la façon dont 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 file d'attente des messages pour une utilisation ultérieure, comme une tâche ou une transaction.

0 votes

Qui avait du sens fr.wikipedia.org/wiki/Command_Pattern Le client et l'invocateur sont liés, mais en même temps, ils ne savent rien l'un de l'autre !

26voto

ragu.pattabi Points 2711

Réponse à une très vieille question. (quelqu'un voit-il les dernières réponses au lieu des plus votées ?)

Il s'agit d'une confusion valable en raison des similitudes. Les modèles de stratégie et de commandement utilisent tous deux encapsulation . Mais cela ne les rend pas identiques.

La différence essentielle est de comprendre ce que est encapsulé. Le principe OO, dont dépendent les deux patrons, est le suivant Encapsuler ce qui varie .

En cas de stratégie, ce qui varie est algorithme . Par exemple, un objet stratégique sait comment produire un fichier XML, tandis que l'autre produit un fichier JSON, par exemple. Des algorithmes différents sont conservés ( encapsulé ) dans des classes différentes. C'est aussi simple que cela.

En cas de commandement, ce qui varie est le demande lui-même. La demande peut provenir de File Menu > Delete o Right Click > Context Menu > Delete o Just Delete Button pressed . Ces trois cas peuvent générer 3 objets de commande du même type. Ces objets de commande ne représentent que 3 demandes de suppression, et non l'algorithme de suppression. Puisque les demandes sont maintenant des objets, nous pouvons les gérer facilement. Soudain, il devient trivial de fournir des fonctionnalités telles que undo ou redo.

La façon dont la commande met en œuvre la logique demandée n'a pas d'importance. En appelant execute(), elle peut mettre en œuvre un algorithme pour déclencher la suppression ou elle peut même le déléguer à d'autres objets, voire à une stratégie. Il ne s'agit que d'un détail d'implémentation du pattern command. C'est pourquoi il est appelé commande bien que ce ne soit pas une façon polie de demande :--)

Contrairement à la stratégie, ce modèle ne s'intéresse qu'à l'action réelle. logique qui est exécuté. Si nous faisons cela, cela permet d'obtenir différentes combinaisons de comportements avec un ensemble minimal de classes, évitant ainsi l'explosion des classes.

Je pense que Command nous aide à élargir notre compréhension de l'encapsulation tandis que Strategy permet une utilisation naturelle de l'encapsulation et du polymorphisme.

15voto

MStodd Points 2806

Selon moi, vous avez plusieurs façons de faire la même chose, chacune d'entre elles est une stratégie, et quelque chose au moment de l'exécution détermine quelle stratégie sera exécutée.

Essayez d'abord la Stratégie 1, si les résultats ne sont pas assez bons, essayez la Stratégie 2...

Les commandes sont liées à des choses distinctes qui doivent se produire, comme la commande TryToWalkAcrossTheRoomCommand. Cette commande sera lancée chaque fois qu'un objet essaiera de traverser la pièce, mais à l'intérieur de celle-ci, il pourra essayer la Stratégie 1 et la Stratégie 2 pour essayer de traverser la pièce.

Mark

2 votes

RE : "plusieurs façons de faire la même chose" - Cela semble être en contradiction avec certains des exemples courants de stratégie. En particulier ceux où il y a des classes d'implémentation qui font des additions, des soustractions, des multiplications, etc. Peut-être que ce ne sont pas de bons exemples ?

1 votes

JoshuaDavis, tous ces "substrats" sont des cas particuliers d'une stratégie : opération arithmétique . ils ont des arguments communs (2 opérandes) et produisent une valeur comme résultat. ils font à peu près la même chose (étant des boîtes noires), mais de façon différente, selon l'implémentation. je ne vois donc pas de conflit ici, mais plutôt le contraire : bel exemple =)

7voto

dma_k Points 3567

Je peux me tromper dans mon opinion, mais je traite la commande comme fonction-à-exécuter, ou réaction. Il doit y avoir au moins deux acteurs : celui qui demande l'action et celui qui l'exécute. L'interface graphique est un exemple typique du modèle de commande :

  • Tous les boutons de la barre d'outils de l'application sont associés à une action.
  • Le bouton est l'exécuteur dans ce cas.
  • Dans ce cas, c'est l'action qui commande.

La commande est généralement limitée à une certaine portée ou à un domaine d'activité, mais ce n'est pas nécessaire : vous pouvez avoir des commandes qui émettent une facture, démarrent une fusée ou suppriment un fichier en implémentant la même interface (par exemple, unique execute() ) dans une seule application. Souvent, les commandes sont autonomes, c'est-à-dire qu'elles n'ont besoin de rien de la part de l'exécuteur pour traiter la tâche à laquelle elles sont destinées (toutes les informations nécessaires sont données au moment de la construction), parfois les commandes sont sensibles au contexte et doivent être capables de découvrir ce contexte ( Retour en arrière doit connaître la position du signe d'insertion dans le texte pour supprimer correctement le caractère précédent ; Rollback doit découvrir la transaction courante à annuler ; ...).

El stratégie est un peu différent : il est davantage lié à une zone. La stratégie peut définir une règle pour formater une date (en UTC ? en fonction de la locale ?) (stratégie "formateur de date") ou pour calculer un carré pour une figure géométrique (stratégie "calculateur de carré"). Les stratégies sont en ce sens des objets de type "flyweight", qui prennent quelque chose en entrée ("date", "figure", ...) et prennent une décision sur cette base. Un exemple de stratégie, qui n'est peut-être pas le meilleur, mais un bon exemple, est celui qui est lié à javax.xml.transform.Source selon que l'objet transmis est DOMSource o SAXSource o StreamSource la stratégie (= transformateur XSLT dans ce cas) appliquera des règles différentes pour le traiter. L'implémentation peut être un simple switch ou impliquer Schéma de la chaîne de responsabilité .

Mais il y a bien un point commun entre ces deux modèles : les commandes et les stratégies encapsulent les algorithmes dans le même domaine sémantique.

1 votes

Je traite la commande comme une fonction de rappel, ou une réaction. Il doit y avoir au moins deux joueurs : un qui demande l'action, et un qui l'exécute... - Je comprends ce que vous essayez de dire, mais j'éviterais d'utiliser le mot "callback", parce que souvent le mot "callback" implique une invocation asynchrone et vous n'avez pas besoin de faire des invocations asynchrones pour que le modèle de commande soit utile. Un exemple concret : Microsoft Word. Les clics sur les boutons de la barre d'outils et les pressions sur les touches de raccourci n'invoquent pas de commandes asynchrones, mais nous pouvons comprendre l'utilité du modèle de commande dans ce cas.

0 votes

Je suis d'accord, bien que, comme Jim l'a dit, je modifierais le texte pour supprimer la référence au callback.

0 votes

Merci, j'ai fait quelques extensions. Faites-moi savoir si vous êtes d'accord ou non.

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