Le Patron de Conception Commande
Le patron Commande est une approche structurelle qui encapsule une requête en tant qu'objet, permettant ainsi la paramétrisation des clients avec différentes requêtes, la mise en file d'attente ou la journalisation des requêtes, et la prise en charge des opérations annulables. Il dissocie l'objet qui invoque l'opération de l'objet qui exécute l'opération. Imaginez une télécommande universelle : chaque bouton est une commande qui exécute une action spécifique sur un appareil sans que l'utilistaeur n'ait à connaître les détails de cette exécution. Voici une illustration en Java : #### Interface pour une Action Exécutable
public interface ActionExecutable {
void executer();
}
Un Périphérique Cible : Une Lampe
public class Lampe {
private String nom;
public Lampe(String nom) {
this.nom = nom;
}
public void allumer() {
System.out.println(nom + " : Lumière allumée.");
}
public void eteindre() {
System.out.println(nom + " : Lumière éteinte.");
}
}
Implémentations de Commandes Spécifiques
public class CommandeAllumerLumiere implements ActionExecutable {
private Lampe cible;
public CommandeAllumerLumiere(Lampe cible) {
this.cible = cible;
}
@Override
public void executer() {
cible.allumer();
}
}
public class CommandeEteindreLumiere implements ActionExecutable {
private Lampe cible;
public CommandeEteindreLumiere(Lampe cible) {
this.cible = cible;
}
@Override
public void executer() {
cible.eteindre();
}
}
L'Invoker : Un Contrôleur Simple
public class ControleurSimple {
private ActionExecutable commandeCourante;
public void definirCommande(ActionExecutable nouvelleCommande) {
this.commandeCourante = nouvelleCommande;
}
public void declencherAction() {
if (commandeCourante != null) {
commandeCourante.executer();
}
}
}
Exemple d'Utilisation
public class DemonstrationCommande {
public static void main(String[] args) {
ControleurSimple telecommande = new ControleurSimple();
Lampe chambreLampe = new Lampe("Lampe de chambre");
// Création des commandes
ActionExecutable allumerChambre = new CommandeAllumerLumiere(chambreLampe);
ActionExecutable eteindreChambre = new CommandeEteindreLumiere(chambreLampe);
// Allumer la lumière
telecommande.definirCommande(allumerChambre);
telecommande.declencherAction();
// Éteindre la lumière
telecommande.definirCommande(eteindreChambre);
telecommande.declencherAction();
}
}
Ce patron de conception est particulièrement utile pour réaliser un couplage faible entre les invocateurs et les récepteurs, améliorer la flexibilité du système et simplifier l'ajout de nouvelles commandes sans modifier le code existant de l'invocateur. Il peut également servir de base pour des fonctionnalités avancées comme les annulations, les transactions ou les journaux d'actions. ### Le Patron de Conception Proxy
Le patron Proxy fournit un substitut ou un mandataire pour un autre objet afin de contrôler l'accès à cet autre objet. Le proxy peut être utilisé pour diverses raisons, telles que la gestion de l'accès à des ressources coûteuses, la sécurisation ou l'ajout de fonctionnalités supplémentaires avant ou après l'appel à l'objet réel. Les points essentiels du patron Proxy incluent : - **Proxy Distant (Remote Proxy)** : Gère l'interaction avec un objet situé dans un espace d'adressage différent, comme un serveur distant.
- **Proxy Virtuel (Virtual Proxy)** : Contrôle l'accès à un objet dont la création est coûteuse, en retardant son instantiation jusqu'à ce qu'il soit réellemant nécessaire (lazy loading).
- **Proxy de Protection (Protection Proxy)** : Contrôle l'accès aux méthodes d'un objet en fonction des droits de l'appelant.
- **Proxy de Journalisation (Logging Proxy)** : Enregistre les appels de méthode avant ou après leur exécution.
Bien que structurellement similaire au patron Décorateur (les deux enveloppent un autre objet), le Proxy a un objectif distinct : contrôler l'accès à l'objet enveloppé, tandis que le Décorateur vise à ajouter des responsabilités. Le framework Java propose des mécanismes pour créer des proxies dynamiques, souvent utilisés dans des contextes de frameworks (comme Spring AOP) ou de RPC pour intercepter les appels de méthode à la volée. ### Le Patron de Conception Stratégie
Le patron Stratégie définit une famille d'algorithmes, les encapsule chacun et les rend interchangeables. Il permet à l'algorithme de varier indépendamment des clients qui l'utilisent. L'objectif principal est de remplacer les longues chaînes de conditions (comme les if/else ou switch) par un ensemble d'objets interchangeables, améliorant ainsi la maintenabilité et l'extensibilité du code. Voici quelques scénarios d'application courants : - Lorsqu'un objet doit choisir dynamiquement entre plusieurs comportements similaires.
- Quand un système nécessite la sélection d'un algorithme parmi plusieurs options au moment de l'exécution.
- Pour éviter d'utiliser de multiples instructions conditionnelles pour implémenter de nombreux comportements dans une seule classe.
Interface pour une Opération Mathématique
public interface OperationMathematique {
int executer(int valeur1, int valeur2);
}
Implémentations de Stratégies Spécifiques
public class StrategieAddition implements OperationMathematique {
@Override
public int executer(int valeur1, int valeur2) {
return valeur1 + valeur2;
}
}
public class StrategieSoustraction implements OperationMathematique {
@Override
public int executer(int valeur1, int valeur2) {
return valeur1 - valeur2;
}
}
public class StrategieMultiplication implements OperationMathematique {
@Override
public int executer(int valeur1, int valeur2) {
return valeur1 * valeur2;
}
}
Le Contexte Utilisant la Stratégie
public class CalculatriceContext {
private OperationMathematique strategie;
public CalculatriceContext(OperationMathematique strategie){
this.strategie = strategie;
}
public int effectuerCalcul(int valeur1, int valeur2){
return strategie.executer(valeur1, valeur2);
}
}
Exemple de Démonstration
public class DemoStrategie {
public static void main(String[] args) {
CalculatriceContext contexte = new CalculatriceContext(new StrategieAddition());
System.out.println("15 + 7 = " + contexte.effectuerCalcul(15, 7));
contexte = new CalculatriceContext(new StrategieSoustraction());
System.out.println("15 - 7 = " + contexte.effectuerCalcul(15, 7));
contexte = new CalculatriceContext(new StrategieMultiplication());
System.out.println("15 * 7 = " + contexte.effectuerCalcul(15, 7));
}
}
L'avantage majeur du patron Stratégie est sa capacité à permettre l'introduction de nouvelles stratégies sans modifier le code client ou le contexte, garantissant une grande flexibilité et facilitant l'évolution du système. Il favorise un code plus propre et plus facile à tester en isolant les algorithmes dans leurs propres classes.