|
Design Patern - Améliorez l'architecture de vos programmes
4.Les patterns de comportement
4.1.Commande
4.1.1. Théorie
Le principale objectif
de ce Design Pattern est d’encapsuler une requête
sous forme d’objet. Vous pouvez utiliser ce pattern lorsque :
-
vous voulez paramétrer des objets pour réaliser
certaines actions avec différentes requêtes
-
pour spécifier, mettre en file, et exécuter
des requêtes à des moments différents
-
pour implémenter des opérations
réversibles
-
pour structurer un système à l’aide
d’opérations de haut niveau construites à partir
d’opérations primitives.
4.1.2. Structure
Ce design pattern est représenté
par :
-
une interface Command qui définit
les méthodes de la commande qui devront être
implémentées.
-
une classe ConcreteCommand qui implémente
l’interface Command servant à définir la
jonction entre l’ objet « Receiver »
et les actions à effectuer.
-
une classe « Client » qui
génère les « Command »

4.1.3.Pratique
Ce design pattern est
très utilisé dans le monde Java et de la programmation
objet. En effet il se retrouve dans les applications utilisant les
files d’attentes, les logs, les supports d’opérations
reversibles (“undo”)…
Le meilleure et le plus
connu des exemples est sans doute celui de Swing. En effet,
cette librairie l’utilise grandement pour les actions associées
aux contrôles (boutons, images …).
Dans le monde J2EE (Java Entreprise) c’est
« Struts » qui utilise à merveille ce
pattern.
Nous allons donc voir ici un exemple très
basique qui permet de gérer les actions afin de pouvoir
revenir en « arrière » dans une
application (undo) ou de revenir en avant (redo). L’application
ici est une calculatrice de base faisant les opérations de
base.
package
command;
public
interface
Command {
public
void execute();
public
void unExecute();
}
-
L’implémentation de Command :
CalculCommand
package
command;
public
class
CalculCommand implements
Command {
protected
Calculator receiver;
protected
char operator;
protected
int operand;
public
CalculCommand(Calculator receiver, char
operator, int
operand) {
this.receiver
= receiver;
this.operator
= operator;
this.operand
= operand;
}
public
void execute() {
receiver.operation(operator,
operand);
}
public
void unExecute() {
receiver.operation(undo(operator),
operand);
}
private
char undo(char
operator) {
char
undo = 0;
switch
(operator) {
case
'+':
undo
= '-';
break;
case
'-':
undo
= '+';
break;
case
'*':
undo
= '/';
break;
case
'/':
undo
= '*';
break;
}
return
undo;
}
}
-
Le « receiver » (classe
Calculator) :
package
command;
public
class Calculator {
private
int total = 0;
public
Calculator() {
}
public
void
operation(char
operator, int
operand) {
switch
(operator) {
case
'+':
total
+= operand;
break;
case
'-':
total
-= operand;
break;
case
'*':
total
*= operand;
break;
case
'/':
total
/= operand;
break;
}
System.out.println("Total
: " +
this.total);
}
}
-
L’ « invoker » (classe
Invoker) :
package
command;
import
java.util.ArrayList;
public
class Invoker {
private
Calculator calculator;
private
ArrayList commands;
private
int current;
public
Invoker() {
calculator
= new
Calculator();
commands
= new
ArrayList();
current
= 0;
}
public
void redo(int
levels) {
System.out.println("Redo
: " + levels + "
levels");
for
(int
i = 0; i < levels; i++) {
if
(current <
commands.size() - 1) {
((Command)
commands.get(current++)).execute();
}
}
}
public
void undo(int
levels) {
System.out.println("Undo
: " + levels + "
levels");
for
(int
i = 0; i < levels; i++) {
if
(current > 0) {
((Command)
commands.get(--current)).unExecute();
}
}
}
public
void compute(char
operator, int
operand) {
Command
command = new
CalculCommand(calculator, operator, operand);
command.execute();
commands.add(command);
current++;
}
}
package
command;
public
class Client {
public
static void main(String []args) {
Invoker
ink = new
Invoker();
ink.compute('+',
100);
ink.compute('-',
50);
ink.compute('*',
10);
ink.compute('/',
2);
ink.undo(4);
ink.redo(3);
}
}
|
|
 |