Pattern dello Stato
Fa parte della sezione Programmazione orientata agli oggetti del percorso C# di Coddy. Lezione 60 di 70.
Il pattern State è un pattern comportamentale che consente a un oggetto di cambiare comportamento quando cambia il suo stato interno. Invece di usare istruzioni condizionali complesse per gestire stati diversi, incapsuli ogni stato nella propria classe e deleghi il comportamento all'oggetto dello stato corrente.
Il pattern è costituito da tre componenti: un'interfaccia di stato che definisce il comportamento specifico dello stato, classi di stato concrete che implementano tale comportamento e una classe contesto che mantiene un riferimento allo stato corrente:
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");
}
}Il contesto contiene lo stato corrente e gli delega le azioni. Gli oggetti stato possono attivare transizioni chiamando SetState() sul contesto:
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(); // Passaggio alla moderazione
doc.Publish(); // Pubblicazione del documento
doc.Publish(); // Già pubblicatoIl pattern State elimina le istruzioni if-else o switch troppo estese che controllano lo stato corrente. Ogni classe di stato gestisce solo il proprio comportamento, rendendo il codice più facile da mantenere ed estendere con nuovi stati.
Sfida
FacileCostruiamo un sistema di semafori usando il pattern State. I semafori passano ciclicamente attraverso stati distinti (rosso, giallo, verde) e ogni stato determina cosa succede quando il semaforo cambia. Invece di usare condizionali complessi, incapsulerai ogni stato del semaforo nella propria classe.
Organizzerai il codice in tre file:
TrafficLightState.cs: Definisci un'interfacciaITrafficLightStatenello spazio dei nomiTrafficcon un metodoChange(TrafficLight light). Poi crea tre classi di stato concrete:RedState- quando viene chiamatoChange, stampaRed - Stop! Changing to Green...e porta il semaforo allo statoGreenStateGreenState- stampaGreen - Go! Changing to Yellow...e passa allo statoYellowStateYellowState- stampaYellow - Caution! Changing to Red...e passa allo statoRedState
TrafficLight.cs: Crea una classeTrafficLightnello stesso spazio dei nomi. Questa è la classe contesto che mantiene lo stato corrente. Per impostazione predefinita, dovrebbe iniziare nello statoRedStatee avere:- Un metodo
SetState(ITrafficLightState state)che gli oggetti di stato usano per attivare le transizioni - Un metodo
Change()che delega al metodoChangedello stato corrente
- Un metodo
Program.cs: Metti insieme tutti gli elementi creando unTrafficLighte passando da uno stato all'altro in base all'input.
Riceverai un input:
- Il numero di volte in cui cambiare il semaforo (un numero intero)
Crea un TrafficLight (che inizia con il rosso) e chiama Change() il numero di volte specificato.
Ad esempio, se l'input è 3, l'output dovrebbe essere:
Red - Stop! Changing to Green...
Green - Go! Changing to Yellow...
Yellow - Caution! Changing to Red...Se l'input è 5, il semaforo compie un giro completo:
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...Nota come la classe TrafficLight non contenga alcuna logica sul significato di ciascun colore o su quale venga dopo: tutte queste informazioni si trovano nelle singole classi di stato. Ogni stato è responsabile del proprio comportamento e di attivare la transizione allo stato successivo!
Provalo tu
using System;
using Traffic;
class Program
{
public static void Main(String[] args)
{
// Leggi il numero di volte in cui cambiare il semaforo
int n = Convert.ToInt32(Console.ReadLine());
// TODO: Crea un'istanza di TrafficLight (inizia in RedState per impostazione predefinita)
// TODO: Chiama il metodo Change() n volte usando un ciclo
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniNamespace e direttiveIntroduzione a classi e oggettiLa parola chiave "this"Metodi e parametriCampi e proprietàCostruttoriInizializzatori di oggettiRiepilogo - Calcolatrice semplice4Ereditarietà
Sintassi di base dell'ereditarietà (:)La parola chiave 'base'Parole chiave virtual e overrideClassi sealedLa classe base 'object'Riepilogo - Gerarchia dei dipendenti7Funzionalità avanzate
Sovraccarico degli operatoriIndicizzatori (this[])Override di ToString()Metodi di estensioneRiepilogo - Lista personalizzata10Pattern di progettazione Parte 1
Introduzione ai pattern di progettazioneSingleton thread-safePattern FactoryPattern Observer (eventi)Pattern Strategy2Proprietà e membri statici
Proprietà implementate automaticamenteProprietà di sola lettura e di sola scritturaCampi e metodi staticiClassi staticheMembri con corpo di espressione5Polimorfismo e interfacce
Polimorfismo a compile time e runtimeInterfaccia o classe astrattaInterfacce multipleInterfacce espliciteUpcasting e downcastingRipasso: calcolatore di forme8Concetti avanzati di programmazione a oggetti
Composizione invece dell'ereditarietàTipi generici (classi e metodi)Delegati ed eventiAttributi e reflectionIDisposable e istruzione usingNozioni di base sull'iniezione delle dipendenze11Pattern di progettazione, parte 2
Pattern del ComandoPattern dell’AdattatorePattern del DecoratorePattern Template MethodPattern dello StatoPattern Composito3Architettura delle classi
Dati di istanza vs staticiParole chiave 'readonly' e 'const'Campi di supportoRiepilogo - Gestore di conti bancari6Incapsulamento
Modificatori di accessoProprietà per l'incapsulamentoImplementazione dell'occultamento dei datiModelli di immutabilitàRiepilogo - Registri degli studentiEsercitati da solo: Compilatore C# online