Menu
Coddy logo textTech

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.

challenge icon

Sfida

Facile

Costruiamo 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'interfaccia DocumentState che tutti gli stati implementeranno. Dovrebbe dichiarare due metodi: edit(Document doc) per tentare di modificare il documento e approve(Document doc) per tentare di approvare/avanzare il documento alla fase successiva.
  • States.java: Crea tre classi concrete di stato che implementano DocumentState:

    DraftState - Quando viene chiamato edit, stampa Editing draft.... Quando viene chiamato approve, stampa Draft approved. Moving to review. e passa il documento a ReviewState.

    ReviewState - Quando viene chiamato edit, stampa Cannot edit during review. (senza modificare lo stato). Quando viene chiamato approve, stampa Review complete. Publishing document. e passa a PublishedState.

    PublishedState - Quando viene chiamato edit, stampa Cannot edit published document.. Quando viene chiamato approve, stampa Document already published.. Nessuna delle due azioni modifica lo stato.

  • Document.java: Crea la classe contesto che mantiene lo stato corrente. Il tuo Document dovrebbe avere:

    Un campo privato che contiene il DocumentState corrente, inizializzato a DraftState nel costruttore.

    Un metodo setState(DocumentState state) che modifica lo stato corrente.

    Un metodo edit() che delega al metodo edit dello stato corrente.

    Un metodo approve() che delega al metodo approve dello stato corrente.

    Un metodo getStatus() che restituisce il nome semplice della classe dello stato corrente (usa getClass().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 è edit oppure approve (per esempio: edit,approve,edit,approve).

    Crea un Document e stampa il suo stato iniziale nel formato Status: [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: PublishedState

Nota 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
    }
}
quiz iconMettiti alla prova

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

Esercitati da solo: Compilatore Java online