« Patrons de conception/Commande » : différence entre les versions

Un livre de Wikilivres.
imported>Chlewbot
m robot Ajoute: de
(Aucune différence)

Version du 6 février 2006 à 11:15

En génie logiciel, Commande est un motif de conception (design pattern) de type comportemental qui encapsule la notion d'invocation. Il permet de séparer complètement le code initiateur de l'action, du code de l'action elle-même. Ce motif de conception est souvent utilisé dans les GUIs où, par exemple, un item de menu peut être connecté à différentes Commandes de façons à ce que l'objet d'item de menu n'ait pas besoin de connaitre les détails de l'action effectuée par la Commande.

A utiliser lorsque: il y a profilération de méthodes similaires, et que le code de l'interface devient difficile à maintenir.

Symptômes:

  • Les objets possèdent trop de méthodes publiques à l'usage d'autres objets.
  • L'interface est inexploitable et on la modifie tout le temps.
  • Les noms des méthodes deviennent de longues périphrases.

Un objet Commande sert à communiquer une action à effectuer, ainsi que les arguments requis. L'objet est envoyé à une seule méthode dans une classe, qui traite les Commandes du type requis. L'objet est libre d'implémenter le traitement de la Commande par un switch, ou un appel à d'autre méthodes (notamment des méthodes surchargées dans les sous-classes). Cela permet d'apporter des modifications aux Commandes définies simplement dans la définition de la Commande, et non dans chaque classe qui utilise la Commande.

Exemple

En Perl :

 # exemple de style "switch":

 sub doCommand {
   my $me = shift;
   my $cmd = shift; $cmd->isa('BleahCommand') or die;
   my $instr = $cmd->getInstructionCode();
   if($instr eq 'PUT') {
     # PUT logic here
   } elsif($instr eq 'GET') {
     # GET logic here
   }
   # etc
 }

 # exemple de style "appel de méthode":
 
 sub doCommand {
   my $me = shift;
   my $cmd = shift; $cmd->isa('BleahCommand') or die;
   my $instr = $cmd->getInstructionCode();
   my $func = "process_" . $instr;
   return undef unless defined &$func;
   return $func->($cmd, @_);
 }

 # exemple de style "sous-classe".
 # on suppose que %commandHandlers contient une liste de pointeurs d'objets.

 sub doCommand {
   my $me = shift;
   my $cmd = shift; $cmd->isa('BleahCommand') or die;
   my $insr = $cmd->getInstructionCode();
   my $objectRef = $commandHandlers{$instr};
   return $objectRef ? $objectRef->handleCommand($cmd, @_) : undef;
 }

Comme Perl dispose d'un AUTOLOAD, le principe pourrait être émulé. Si un package voulait effectuer un ensemble de commandes arbitrairement grand, il pourrait recenser toutes les méthodes undefined grâce à AUTOLOAD, puis tenter de les répartir (ce qui suppose que %commandHandlers contient une table de pointeurs, dont les clés sont les noms des méthodes):

 sub AUTOLOAD {
   my $me = shift;
   (my $methodName) = $AUTOLOAD m/.*::(\w+)$/;
   return if $methodName eq 'DESTROY';
   my $objectRef = $commandHandlers{$methodName};
   return $objectRef ? $objectRef->handleCommand($methodName, @_) : undef;
 }

Cela convertit les appels aux différentes méthodes dans l'objet courant, en appels à une méthode handleCommand dans différents objets. Cet exemple utilise Perl pour adapter un motif de conception à base d'objets Commandes, dans une interface qui en est dépourvue.