Menu
Coddy logo textTech

Patron État

Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 74 sur 87.

Le State Pattern est un patron de conception comportemental qui permet à un objet de modifier son comportement lorsque son état interne change. L'objet semble changer de classe, mais en réalité, il délègue le comportement à différents objets d'état. Pensez à un distributeur automatique : sa réponse à l'appui sur un bouton dépend de s'il est au repos, si de l'argent a été inséré ou s'il est en train de distribuer un produit.

Au lieu d'utiliser des instructions conditionnelles complexes pour gérer différents états, vous encapsulez chaque état dans sa propre classe. Le patron implique un Context qui maintient une référence vers l'état actuel, et des classes State qui définissent le comportement pour chaque état :

interface State {
    void handle(Context context);
}

class Context {
    private State state;
    
    public void setState(State state) {
        this.state = state;
    }
    
    public void request() {
        state.handle(this);
    }
}

Chaque état concret implémente le comportement et peut déclencher des transitions vers d'autres états :

class IdleState implements State {
    public void handle(Context context) {
        System.out.println("Idle: Insert coin to start");
        context.setState(new ActiveState());
    }
}

class ActiveState implements State {
    public void handle(Context context) {
        System.out.println("Active: Processing...");
        context.setState(new IdleState());
    }
}

Le contexte délègue les requêtes à son état actuel, et le comportement change automatiquement à mesure que l'état change :

Context context = new Context();
context.setState(new IdleState());

context.request();  // Inactif : Insérez une pièce pour démarrer
context.request();  // Actif : Traitement en cours...

Le State Pattern est idéal lorsque le comportement d'un objet dépend fortement de son état et doit changer à l'exécution. Il élimine les gros blocs conditionnels et rend l'ajout de nouveaux états simple — il suffit de créer une nouvelle classe implémentant l'interface State.

challenge icon

Défi

Facile

Construisons un système de flux de travail de documents en utilisant le State Pattern ! Vous allez créer un système qui modélise la façon dont un document passe par différentes étapes — Draft, Review et Published — chaque état déterminant quelles actions sont disponibles et comment le document se comporte lorsque vous essayez de le modifier ou de l'approuver.

Vous organiserez votre code sur quatre fichiers :

  • DocumentState.java : Définissez l'interface DocumentState que tous les états implémenteront. Elle doit déclarer deux méthodes : edit(Document doc) pour tenter de modifier le document, et approve(Document doc) pour tenter d'approuver/faire passer le document à l'étape suivante.
  • States.java : Créez trois classes d'états concrètes qui implémentent DocumentState :

    DraftState - Lorsque edit est appelé, affichez Editing draft.... Lorsque approve est appelé, affichez Draft approved. Moving to review. et faites passer le document à ReviewState.

    ReviewState - Lorsque edit est appelé, affichez Cannot edit during review. (pas de changement d'état). Lorsque approve est appelé, affichez Review complete. Publishing document. et passez à PublishedState.

    PublishedState - Lorsque edit est appelé, affichez Cannot edit published document.. Lorsque approve est appelé, affichez Document already published.. Aucune des deux actions ne change l'état.

  • Document.java : Créez la classe de contexte qui maintient l'état actuel. Votre Document doit avoir :

    Un champ privé contenant le DocumentState actuel, initialisé à DraftState dans le constructeur.

    Une méthode setState(DocumentState state) qui change l'état actuel.

    Une méthode edit() qui délègue à la méthode edit de l'état actuel.

    Une méthode approve() qui délègue à la méthode approve de l'état actuel.

    Une méthode getStatus() qui retourne le nom simple de la classe de l'état actuel (utilisez getClass().getSimpleName()).

  • Main.java : Démontrez votre système d'états ! Vous recevrez une entrée : une séquence d'actions sous forme de chaîne de caractères séparée par des virgules où chaque action est soit edit soit approve (par exemple : edit,approve,edit,approve).

    Créez un Document et affichez son statut initial au format Status: [state]. Ensuite, traitez chaque action dans l'ordre, en appelant la méthode appropriée sur le document. Après chaque action, affichez le statut actuel.

Vous recevrez une entrée : une chaîne d'actions séparée par des virgules.

Par exemple, avec l'entrée edit,approve,approve, votre sortie serait :

Status: DraftState
Editing draft...
Status: DraftState
Draft approved. Moving to review.
Status: ReviewState
Review complete. Publishing document.
Status: PublishedState

Remarquez comment le même appel à approve() produit des résultats différents selon l'état actuel du document — c'est l'essence même du State Pattern ! Le document n'utilise pas de conditions pour vérifier son état ; au lieu de cela, il délègue le comportement à l'objet d'état actuel, qui gère l'action de manière appropriée et déclenche les transitions si nécessaire.

Aide-mémoire

Le State Pattern est un patron de conception comportemental qui permet à un objet de changer son comportement lorsque son état interne change en déléguant le comportement à différents objets d'état au lieu d'utiliser des instructions conditionnelles complexes.

Le patron se compose d'un Context qui maintient une référence à l'état actuel, et de classes State qui définissent le comportement pour chaque état :

interface State {
    void handle(Context context);
}

class Context {
    private State state;
    
    public void setState(State state) {
        this.state = state;
    }
    
    public void request() {
        state.handle(this);
    }
}

Chaque état concret implémente le comportement et peut déclencher des transitions vers d'autres états :

class IdleState implements State {
    public void handle(Context context) {
        System.out.println("Idle: Insert coin to start");
        context.setState(new ActiveState());
    }
}

class ActiveState implements State {
    public void handle(Context context) {
        System.out.println("Active: Processing...");
        context.setState(new IdleState());
    }
}

Le contexte délègue les requêtes à son état actuel, et le comportement change automatiquement à mesure que l'état change :

Context context = new Context();
context.setState(new IdleState());

context.request();  // Idle: Insert coin to start
context.request();  // Active: Processing...

Le State Pattern est idéal lorsque le comportement d'un objet dépend fortement de son état et doit changer au moment de l'exécution. Il élimine les grands blocs conditionnels et rend l'ajout de nouveaux états simple.

Essayez vous-même

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        
        // TODO: Créer un nouveau Document
        
        // TODO: Afficher le statut initial au format "Status: [state]"
        
        // TODO: Diviser l'entrée par la virgule pour obtenir les actions individuelles
        
        // TODO: Parcourir chaque action
        // - Si l'action est "edit", appeler edit() sur document
        // - Si l'action est "approve", appeler approve() sur document
        // - Après chaque action, afficher le statut actuel
    }
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet