Introduzione
Il pattern state consente ad un oggetto di cambiare il proprio comportamento a run-time in funzione dello stato in cui si trova. Esso è un pattern comportamentale.
Questo pattern viene usato tipicamente quando voglio implementare una macchina a stati finiti.
In ogni momento il programma può quindi essere in uno e un solo stato ed è necessario definire le condizioni per passare da uno stato all’altro.
Consiglio quindi, prima di procedere con l’implementazione, scrivere il diagramma a stati finiti che si vuole implementare.
Prendiamo l’esempio di un apparecchio telefonico: esso è perennemente nello stato di attesa fino a che non riceve una chiamata. Quando la riceve cambia di stato e va nello stato chiamata dove il telefono squilla. Da questo stato l’utente può rifiutare e quindi ritornare nello stato di Attesa oppure accettare: ho quindi due transizioni diverse.
Se rifiuta si ritorna allo stato di Attesa come sopra, se invece accetta si passa allo stato Conversazione. Una volta terminata la conversazione si conclude la telefonata tornando in Attesa.
Questo schema è indicato nell’immagine qui sotto
Implementazione C#
Il pattern state si basa su una classe Context
che è l’oggetto che vuole cambiare stato (nell’esempio sopra il telefono) e vari State
che sono gli stati in cui il Context
può essere.
L’esempio seguente è in C# ma il concetto è lo stesso per tutti i linguaggi orientati agli oggetti come Java.
State
Tutti gli stati erediteranno dalla stessa classe astratta (o interfaccia) State
la quale avrà almeno un metodo Handle
, il quale sarà il metodo per il cambio di stato, che dipenderà da Context
.
State concreti
Ho quindi vari State
concreti, in base all’applicazione, che sono tutti gli stati dove può essere il Context
.
Context
Il Context
è l’oggetto di cui voglio modificare il comportamento. Notare la property State
che permette di modificare il suo stato. Questa property dovrà essere settata nei metodi Handle
dei ConcreteState
.
Quando usarlo
Il pattern State permette di sostituire istruzioni condizionali complesse con delle classi le quali contengono, al loro interno, tutte le loro logiche e le transizioni. In questo modo la classe Context, che, senza State, risulterebbe pachidermica, risulta invece piccola e semplice. Rispetto quindi il [Open-closed principle e i [principi di buona programmazione]].
Dove approfondire
Per approfondire consiglio assolutamente la lettura di Head First Design Pattern, un libro imprendiscindibile per chiunque voglia migliorarsi come programmatore.