Pattern State
Fa parte della sezione Programmazione orientata agli oggetti del percorso Java di Coddy. Lezione 74 di 87.
Lo State Pattern è un pattern comportamentale che consente a un oggetto di cambiare comportamento quando cambia il suo stato interno. L'oggetto sembra cambiare classe, ma in realtà delega il comportamento a diversi oggetti di stato. Pensa a un distributore automatico: la sua risposta alla pressione di un pulsante dipende dal fatto che sia inattivo, che sia stato inserito del denaro o che stia erogando un prodotto.
Invece di usare istruzioni condizionali complesse per gestire stati diversi, incapsuli ogni stato nella propria classe. Il pattern prevede un Context che mantiene un riferimento allo stato corrente e classi State che definiscono il comportamento per ogni stato:
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);
}
}Ogni stato concreto implementa il comportamento e può avviare transizioni verso altri stati:
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());
}
}Il contesto delega le richieste allo stato corrente e il comportamento cambia automaticamente al cambiare dello stato:
Context context = new Context();
context.setState(new IdleState());
context.request(); // Inattivo: inserisci una moneta per iniziare
context.request(); // Attivo: elaborazione in corso...Il pattern State è ideale quando il comportamento di un oggetto dipende fortemente dal suo stato e deve cambiare durante l'esecuzione. Elimina grandi blocchi condizionali e semplifica l'aggiunta di nuovi stati: basta creare una nuova classe che implementi l'interfaccia State.
Sfida
FacileCostruiamo un sistema di flusso di lavoro per documenti usando lo State Pattern! Creerai un sistema che modella il modo in cui un documento attraversa diverse fasi, Draft, Review e Published, dove ogni stato determina quali azioni sono disponibili e come si comporta il documento quando provi a modificarlo o approvarlo.
Organizzerai il codice in quattro file:
DocumentState.java: Definisci l'interfacciaDocumentStateche tutti gli stati implementeranno. Dovrebbe dichiarare due metodi:edit(Document doc)per tentare di modificare il documento eapprove(Document doc)per tentare di approvare/avanzare il documento alla fase successiva.States.java: Crea tre classi concrete di stato che implementanoDocumentState:DraftState- Quando viene chiamatoedit, stampaEditing draft.... Quando viene chiamatoapprove, stampaDraft approved. Moving to review.e passa il documento aReviewState.ReviewState- Quando viene chiamatoedit, stampaCannot edit during review.(senza modificare lo stato). Quando viene chiamatoapprove, stampaReview complete. Publishing document.e passa aPublishedState.PublishedState- Quando viene chiamatoedit, stampaCannot edit published document.. Quando viene chiamatoapprove, stampaDocument already published.. Nessuna delle due azioni modifica lo stato.Document.java: Crea la classe contesto che mantiene lo stato corrente. Il tuoDocumentdovrebbe avere:Un campo privato che contiene il
DocumentStatecorrente, inizializzato aDraftStatenel costruttore.Un metodo
setState(DocumentState state)che modifica lo stato corrente.Un metodo
edit()che delega al metodoeditdello stato corrente.Un metodo
approve()che delega al metodoapprovedello stato corrente.Un metodo
getStatus()che restituisce il nome semplice della classe dello stato corrente (usagetClass().getSimpleName()).Main.java: Mostra il funzionamento del tuo sistema di stati! Riceverai un input: una sequenza di azioni come stringa separata da virgole, in cui ogni azione èeditoppureapprove(per esempio:edit,approve,edit,approve).Crea un
Documente stampa il suo stato iniziale nel formatoStatus: [state]. Poi elabora ogni azione in ordine, chiamando il metodo appropriato sul documento. Dopo ogni azione, stampa lo stato corrente.
Riceverai un input: una stringa di azioni separate da virgole.
Per esempio, con l'input edit,approve,approve, il tuo output sarà:
Status: DraftState
Editing draft...
Status: DraftState
Draft approved. Moving to review.
Status: ReviewState
Review complete. Publishing document.
Status: PublishedStateNota come la stessa chiamata a approve() produca risultati diversi a seconda dello stato corrente del documento. Questa è l'essenza dello State Pattern! Il documento non usa condizioni per controllare il proprio stato; delega invece il comportamento all'oggetto di stato corrente, che gestisce l'azione in modo appropriato e attiva le transizioni quando necessario.
Provalo tu
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: Crea un nuovo Document
// TODO: Stampa lo stato iniziale nel formato "Status: [state]"
// TODO: Dividi l'input usando la virgola per ottenere le singole azioni
// TODO: Esegui un ciclo su ogni azione
// - Se l'azione è "edit", chiama edit() su document
// - Se l'azione è "approve", chiama approve() su document
// - Dopo ogni azione, stampa lo stato corrente
}
}
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 a oggetti
File esterniIntroduzione alla programmazione a oggettiClassi e oggettiLa parola chiave thisMetodiCampi (attributi)Metodo costruttoreSovraccarico dei costruttoriRipasso - Calcolatrice semplice4Ereditarietà
Ereditarietà di base (extends)La parola chiave superSovrascrittura dei metodi (@Override)Concatenamento dei costruttoriLa classe ObjectEreditarietà singola e multilivelloPerché non esiste l'ereditarietà multipla delle classiRiepilogo: gerarchia dei dipendenti7Metodi speciali e classe Object
Metodo toString()equals() e hashCode()Metodo clone()compareTo() e ComparableInterfaccia ComparatorRiepilogo - Ordinamento personalizzato2Modificatori di accesso e incapsulamento
Panoramica dei livelli di accessoMetodi getter e setterNascondimento delle informazioniLa parola chiave finalRiepilogo - Gestore di conti bancari5Polimorfismo
Nozioni di base sull'overloading dei metodiOverride dei metodi (a runtime)Upcasting e downcastingL'operatore instanceofClassi e metodi astrattiRiepilogo - Calcolatore di forme8Concetti avanzati di OOP
Composizione vs ereditarietàAggregazione vs composizioneClassi interne, annidate e anonimeEnum e metodi degli EnumRecord (Java 16+)Classi sealed (Java 17+)11Modelli di progettazione Parte 1
Introduzione ai modelli di progettazionePattern SingletonPattern FactoryPattern BuilderPattern ObserverPattern Strategy3Proprietà di classe e membri statici
Variabili di istanza e staticheMetodi staticiBlocchi staticiCostanti (static final)Riepilogo - Contatore e utility6Interfacce e classi astratte
Introduzione alle interfacceImplementazione delle interfacceImplementazione di più interfacceMetodi default e static nelle interfacceClassi astratte e interfacce a confrontoInterfacce funzionaliRiepilogo: sistema di pagamento9Tipi generici
Introduzione ai tipi genericiClassi genericheMetodi genericiParametri di tipo con limitiCaratteri jolly (?, extends, super)Riepilogo - Contenitore generico12Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern IteratorEsercitati da solo: Compilatore Java online