Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Design Patterns en Java
  3. Le pattern State
Extrait - Design Patterns en Java Descriptions et solutions illustrées en UML 2 et Java (5e édition) - Les 23 modèles de conception
Extraits du livre
Design Patterns en Java Descriptions et solutions illustrées en UML 2 et Java (5e édition) - Les 23 modèles de conception Revenir à la page d'achat du livre

Le pattern State

Description

Le pattern State permet à un objet d’adapter son comportement en fonction de son état interne.

Exemple

Nous nous intéressons aux commandes de produits sur notre site de vente en ligne. Elles sont décrites par la classe Commande. Les instances de cette classe possèdent un cycle de vie qui est illustré par le diagramme d’états-transitions de la figure 4-9.1. L’état EnCours est l’état où la commande est en cours de constitution : le client ajoute des produits. L’état Validée est l’état où la commande a été validée et réglée par le client. Enfin l’état Livrée est l’état où les produits ont été livrés.

images/fig251.PNG

Figure 4-9.1 - Diagramme d’états-transitions d’une commande

La classe Commande possède des méthodes dont le comportement diffère en fonction de cet état. Par exemple, la méthode ajouteProduit n’ajoute des produits que si la commande se trouve dans l’état EnCours. La méthode efface n’a pas de comportement dans l’état Livrée.

L’approche traditionnelle pour résoudre ces différences de comportement consiste à utiliser des conditions dans le corps des méthodes. Cette approche conduit souvent à des méthodes complexes à écrire et à appréhender.

Le pattern State propose une autre solution qui consiste...

Structure

1. Diagramme de classes

La figure 4-9.3 illustre la structure générique du pattern.

images/figure25-3.png

Figure 4-9.3 - Structure du pattern State

2. Participants

Les participants au pattern sont les suivants :

  • MachineÉtat (Commande) est une classe concrète décrivant des objets qui sont des machines à états, c’est-à-dire qui possèdent un ensemble d’états pouvant être décrit par un diagramme d’états-transitions. Cette classe maintient une référence vers une instance d’une sous-classe d’État qui définit l’état courant.

  • État (ÉtatCommande) est une classe abstraite qui introduit la signature des méthodes liées à l’état et qui gère l’association avec la machine à états.

  • ÉtatConcretA et ÉtatConcretB (CommandeEnCours, CommandeValidée et CommandeLivrée) sont des sous-classes concrètes qui implantent le comportement des méthodes relativement à chaque état.

3. Collaborations

La machine à états délègue les appels des méthodes dépendant de l’état courant vers un objet d’état.

La machine à états peut transmettre à l’objet d’état une référence vers elle-même si c’est nécessaire....

Domaines d’application

Le pattern est utilisé dans le cas suivant :

  • Le comportement d’un objet dépend de son état.

  • L’implantation de cette dépendance à l’état par des instructions conditionnelles est trop complexe.

Exemple en Java

Nous présentons l’exemple de la figure 4-9.2 en Java. La classe Commande est décrite à la suite. Les méthodes ajouteProduit, retireProduit et efface dépendent de l’état. Par conséquent leur implantation consiste à appeler la méthode correspondante de l’instance référencée par etatCommande.

Le constructeur de la classe initialise l’attribut etatCommande avec une instance de la classe CommandeEnCours. La méthode etatSuivant passe à l’état suivant en associant une nouvelle instance à l’attribut etatCommande.

import java.util.*; 
public class Commande 
{ 
  protected List<Produit> produits = new ArrayList<Produit>(); 
  protected EtatCommande etatCommande; 
 
  public Commande() 
  { 
    etatCommande = new CommandeEnCours(this); 
  } 
 
  public void ajouteProduit(Produit produit) 
  { 
    etatCommande.ajouteProduit(produit); 
  } 
 
  public void retireProduit(Produit produit) 
  { 
    etatCommande.retireProduit(produit); 
  } 
 
  public void efface() 
  { 
    etatCommande.efface(); 
  } 
 
  public void etatSuivant() 
  { 
    etatCommande = etatCommande.etatSuivant(); 
  } 
 ...