Patron État
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy. Leçon 74 sur 87.
Le pattern État 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 son comportement à différents objets d’état. Pensez à un distributeur automatique : sa réponse lorsque vous appuyez sur un bouton dépend du fait qu’il soit en attente, qu’une somme d’argent ait été insérée ou qu’il distribue 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 modèle implique un Contexte qui conserve une référence vers l’état actuel, ainsi que des classes État qui définissent le comportement de 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 lorsque l’état change :
Context context = new Context();
context.setState(new IdleState());
context.request(); // Idle : Insérez une pièce pour commencer
context.request(); // Active : Traitement...Le patron d’état est idéal lorsque le comportement d’un objet dépend fortement de son état et doit changer lors de l’exécution. Il élimine les grands blocs conditionnels et facilite l’ajout de nouveaux états : il suffit de créer une nouvelle classe implémentant l’interface State.
Défi
FacileConstruisons un système de workflow 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, Brouillon, Révision et Publié, chaque état déterminant les actions disponibles et le comportement du document lorsque vous essayez de le modifier ou de l'approuver.
Vous allez organiser votre code sur quatre fichiers :
DocumentState.java: définissez l'interfaceDocumentStateque tous les états implémenteront. Elle doit déclarer deux méthodes :edit(Document doc)pour tenter de modifier le document, etapprove(Document doc)pour tenter d'approuver ou de faire passer le document à l'étape suivante.States.java: créez trois classes d'état concrètes qui implémententDocumentState:DraftState- Lorsqueeditest appelée, affichezEditing draft.... Lorsqueapproveest appelée, affichezDraft approved. Moving to review.et faites passer le document àReviewState.ReviewState- Lorsqueeditest appelée, affichezCannot edit during review.(aucun changement d'état). Lorsqueapproveest appelée, affichezReview complete. Publishing document.et faites passer le document àPublishedState.PublishedState- Lorsqueeditest appelée, affichezCannot edit published document.. Lorsqueapproveest appelée, affichezDocument already published.. Aucune des deux actions ne modifie l'état.Document.java: créez la classe de contexte qui conserve l'état actuel. VotreDocumentdoit avoir :Un champ privé contenant le
DocumentStateactuel, initialisé àDraftStatedans le constructeur.Une méthode
setState(DocumentState state)qui modifie l'état actuel.Une méthode
edit()qui délègue l'appel à la méthodeeditde l'état actuel.Une méthode
approve()qui délègue l'appel à la méthodeapprovede l'état actuel.Une méthode
getStatus()qui renvoie le nom simple de la classe de l'état actuel (utilisezgetClass().getSimpleName()).Main.java: faites une démonstration de votre système d'états ! Vous recevrez une entrée : une séquence d'actions sous forme de chaîne séparée par des virgules, où chaque action est soitedit, soitapprove(par exemple :edit,approve,edit,approve).Créez un
Documentet affichez son état initial au formatStatus: [state]. Traitez ensuite chaque action dans l'ordre, en appelant la méthode appropriée sur le document. Après chaque action, affichez l'état actuel.
Vous recevrez une entrée : une chaîne d'actions séparées 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: PublishedStateRemarquez 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 ; il délègue plutôt le comportement à l'objet d'état actuel, qui gère l'action de manière appropriée et déclenche les transitions lorsque cela est nécessaire.
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 une 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
}
}
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
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesChamps (Attributs)Méthode constructeurSurcharge de constructeurRécapitulatif - Calculatrice simple4Héritage
Héritage de base (extends)Le mot-clé superRedéfinition de méthode (@Override)Chaînage de constructeursLa classe ObjectHéritage simple et multiniveauPourquoi pas d'héritage multiple de classesRécapitulatif - Hiérarchie des employés7Méthodes spéciales et classe Object
Méthode toString()equals() et hashCode()Méthode clone()compareTo() et ComparableInterface ComparatorRécapitulatif - Tri personnalisé2Modificateurs d'accès et Encapsulation
Aperçu des niveaux d'accèsMéthodes Getter et SetterMasquage d'informationsLe mot-clé finalRécapitulatif - Gestionnaire de compte bancaire5Polymorphisme
Bases de la surcharge de méthodesRedéfinition de méthodes (Run-Time)Upcasting et DowncastingL'opérateur instanceofClasses et méthodes abstraitesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageAgrégation vs CompositionClasses internes, imbriquées et anonymesEnums et méthodes d'EnumRecords (Java 16+)Classes scellées (Java 17+)11Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron MonteurPatron ObservateurPatron Stratégie3Propriétés de classe et membres statiques
Variables d'instance vs variables statiquesMéthodes statiquesBlocs statiquesConstantes (static final)Récapitulatif - Compteur et utilitaire6Interfaces et Classes Abstraites
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesDefault et Static dans les InterfacesClasses Abstraites vs InterfacesInterfaces FonctionnellesRécapitulatif - Système de Paiement9La généricité
Introduction à la généricitéClasses génériquesMéthodes génériquesParamètres de type bornésWildcards (?, extends, super)Récapitulatif - Conteneur générique12Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositePatron ItérateurEntraînez-vous par vous-même : Compilateur Java en ligne