Patron État
Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy. Leçon 60 sur 70.
Le patron State est un patron comportemental qui permet à un objet de modifier son comportement lorsque son état interne change. Au lieu d’utiliser des instructions conditionnelles complexes pour gérer différents états, vous encapsulez chaque état dans sa propre classe et déléguez le comportement à l’objet d’état actuel.
Le modèle se compose de trois composants : une interface d’état définissant le comportement propre à chaque état, des classes d’état concrètes implémentant ce comportement et une classe de contexte qui conserve une référence vers l’état actuel :
public interface IDocumentState
{
void Publish(Document doc);
}
public class DraftState : IDocumentState
{
public void Publish(Document doc)
{
Console.WriteLine("Moving to moderation");
doc.SetState(new ModerationState());
}
}
public class ModerationState : IDocumentState
{
public void Publish(Document doc)
{
Console.WriteLine("Publishing document");
doc.SetState(new PublishedState());
}
}
public class PublishedState : IDocumentState
{
public void Publish(Document doc)
{
Console.WriteLine("Already published");
}
}Le contexte contient l’état actuel et lui délègue les actions. Les objets d’état peuvent déclencher des transitions en appelant SetState() sur le contexte :
public class Document
{
private IDocumentState _state = new DraftState();
public void SetState(IDocumentState state) => _state = state;
public void Publish() => _state.Publish(this);
}
var doc = new Document();
doc.Publish(); // Passage en modération
doc.Publish(); // Publication du document
doc.Publish(); // Déjà publiéLe pattern State élimine les instructions if-else ou switch tentaculaires qui vérifient l’état actuel. Chaque classe d’état gère uniquement son propre comportement, ce qui facilite la maintenance du code et son extension avec de nouveaux états.
Défi
FacileConstruisons un système de feu tricolore en utilisant le patron State. Les feux tricolores passent par des états distincts (rouge, jaune, vert), et chaque état détermine ce qui se produit lorsque le feu change. Au lieu d'utiliser des conditions complexes, tu encapsuleras chaque état du feu dans sa propre classe.
Tu organiseras ton code sur trois fichiers :
TrafficLightState.cs: définis une interfaceITrafficLightStatedans l'espace de nomsTrafficavec une méthodeChange(TrafficLight light). Crée ensuite trois classes d'état concrètes :RedState- lorsqueChangeest appelée, elle afficheRed - Stop! Changing to Green...et fait passer le feu àGreenStateGreenState- afficheGreen - Go! Changing to Yellow...et passe àYellowStateYellowState- afficheYellow - Caution! Changing to Red...et passe àRedState
TrafficLight.cs: crée une classeTrafficLightdans le même espace de noms. Il s'agit de ta classe de contexte, qui conserve l'état actuel. Elle doit commencer par défaut dans l'étatRedStateet disposer de :- une méthode
SetState(ITrafficLightState state)que les objets d'état utilisent pour déclencher les transitions - une méthode
Change()qui délègue à la méthodeChangede l'état actuel
- une méthode
Program.cs: assemble tout en créant unTrafficLightet en parcourant les changements d'état en fonction de l'entrée.
Tu recevras une entrée :
- le nombre de fois où modifier le feu tricolore (un entier)
Crée un TrafficLight (qui commence au rouge) et appelle Change() le nombre de fois indiqué.
Par exemple, si l'entrée est 3, la sortie doit être :
Red - Stop! Changing to Green...
Green - Go! Changing to Yellow...
Yellow - Caution! Changing to Red...Si l'entrée est 5, le feu recommence son cycle :
Red - Stop! Changing to Green...
Green - Go! Changing to Yellow...
Yellow - Caution! Changing to Red...
Red - Stop! Changing to Green...
Green - Go! Changing to Yellow...Remarque que la classe TrafficLight ne contient aucune logique concernant la signification de chaque couleur ni ce qui vient ensuite : toutes ces connaissances résident dans les classes d'état individuelles. Chaque état est responsable de son propre comportement et du déclenchement de la transition vers l'état suivant !
Essayez vous-même
using System;
using Traffic;
class Program
{
public static void Main(String[] args)
{
// Lire le nombre de fois que le feu de signalisation doit changer
int n = Convert.ToInt32(Console.ReadLine());
// TODO: Créer une instance de TrafficLight (commence par RedState par défaut)
// TODO: Appeler la méthode Change() n fois en utilisant une boucle
}
}
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 externesEspaces de noms et directivesIntro aux classes et objetsLe mot-clé 'this'Méthodes et paramètresChamps vs PropriétésConstructeursInitialiseurs d'objetsRécapitulatif - Calculatrice simple4Héritage
Syntaxe de base de l'héritage (:)Le mot-clé 'base'Mots-clés Virtual & OverrideClasses scelléesLa classe de base 'object'Récapitulatif - Hiérarchie des employés7Fonctionnalités avancées
Surcharge d'opérateursIndexeurs (this[])Redéfinition de ToString()Méthodes d'extensionRécapitulatif - Liste personnalisée10Patrons de conception - Partie 1
Introduction aux patrons de conceptionSingleton Thread-SafePatron FabriquePatron Observateur (Événements)Patron Stratégie2Propriétés et membres statiques
Propriétés auto-implémentéesPropriétés en lecture/écriture seuleChamps et méthodes statiquesClasses statiquesMembres à corps d'expression5Polymorphisme & Interfaces
Polymorphisme : Compilation vs ExécutionInterface vs Classe AbstraiteInterfaces MultiplesInterfaces ExplicitesUpcasting & DowncastingRécapitulatif - Calculateur de Formes8Concepts avancés de la POO
Composition plutôt qu'héritageGénériques (Classes et Méthodes)Délégués et ÉvénementsAttributs et RéflexionIDisposable et l'instruction usingBases de l'Injection de Dépendances11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Architecture des classes
Données d'instance vs statiquesMots-clés 'readonly' & 'const'Champs de supportRécapitulatif - Gestionnaire de compte bancaire6Encapsulation
Modificateurs d'accèsPropriétés pour l'encapsulationImplémentation du masquage de donnéesPatterns d'immuabilitéRécapitulatif - Dossiers d'étudiants12Projet : Système de gestion de bibliothèque
Structure du projetModèles Livre et UtilisateurLogique du système d'empruntLINQ pour la rechercheInterface Console / Interface d'administrationTests unitaires (NUnit/xUnit)Entraînez-vous par vous-même : Compilateur C# en ligne