Menu
Coddy logo textTech

Pattern State

Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 98 di 110.

Il pattern State consente a un oggetto di cambiare comportamento quando cambia il suo stato interno, facendo sembrare che l'oggetto abbia cambiato classe. Invece di usare condizioni complesse per gestire stati diversi, incapsuli ogni stato nella propria classe e deleghi il comportamento all'oggetto che rappresenta lo stato corrente.

Il pattern è composto da un Context che mantiene un riferimento allo stato corrente e da classi State che definiscono il comportamento per ogni stato possibile. Quando lo stato del context cambia, anche il suo comportamento cambia automaticamente:

abstract class DocumentState {
  void publish(Document doc);
  String getStatus();
}

class DraftState implements DocumentState {
  @override
  void publish(Document doc) {
    print('Moving to review...');
    doc.setState(ReviewState());
  }

  @override
  String getStatus() => 'Draft';
}

class ReviewState implements DocumentState {
  @override
  void publish(Document doc) {
    print('Document published!');
    doc.setState(PublishedState());
  }

  @override
  String getStatus() => 'Under Review';
}

class PublishedState implements DocumentState {
  @override
  void publish(Document doc) {
    print('Already published.');
  }

  @override
  String getStatus() => 'Published';
}

class Document {
  DocumentState _state = DraftState();

  void setState(DocumentState state) => _state = state;
  void publish() => _state.publish(this);
  String getStatus() => _state.getStatus();
}

void main() {
  var doc = Document();
  print(doc.getStatus());  // Draft
  doc.publish();           // Moving to review...
  print(doc.getStatus());  // Under Review
  doc.publish();           // Document published!
  print(doc.getStatus());  // Published
}

Ogni classe di stato gestisce l'azione publish() in modo diverso e può portare il documento allo stato successivo. La classe Document non ha bisogno di istruzioni condizionali per controllare il suo stato attuale: delega semplicemente all'oggetto stato attivo in quel momento. Questo pattern è ideale per gli oggetti con modalità comportamentali distinte, come l'elaborazione degli ordini, i lettori multimediali o i sistemi di flusso di lavoro.

challenge icon

Sfida

Facile

Costruiamo un sistema di semaforo usando il pattern State! Creerai un semaforo che passa attraverso stati diversi, in cui ogni stato determina il colore della luce e il modo in cui passa allo stato successivo.

Organizzerai il codice in due file:

  • traffic_light.dart: questo file contiene le classi degli stati e il contesto del semaforo. Crea una classe astratta TrafficLightState con due metodi: String getColor(), che restituisce il colore attuale della luce, e void next(TrafficLight light), che fa passare la luce allo stato successivo. Implementa tre classi di stato concrete:
    • RedState - restituisce RED come colore e stampa Stop! Light is red. quando viene chiamato next(), quindi passa a GreenState
    • GreenState - restituisce GREEN come colore e stampa Go! Light is green. quando viene chiamato next(), quindi passa a YellowState
    • YellowState - restituisce YELLOW come colore e stampa Caution! Light is yellow. quando viene chiamato next(), quindi passa a RedState
    Poi crea una classe TrafficLight (il contesto) che inizia nello stato RedState. Dovrebbe avere un metodo setState() per cambiare lo stato attuale, un metodo getColor() che delega allo stato attuale e un metodo change() che chiama next() sullo stato attuale.
  • main.dart: importa il file del semaforo e mostra il pattern State in azione. Crea un TrafficLight e stampa il suo colore iniziale. Poi chiama change() tre volte, stampando il colore dopo ogni cambiamento. In questo modo vedrai il semaforo attraversare tutti gli stati e tornare all'inizio.

Nota che la classe TrafficLight non ha bisogno di condizioni per determinare il comportamento: ogni stato conosce il proprio colore e quale stato viene dopo. Il semaforo si limita a delegare allo stato attivo in quel momento!

Output previsto:

RED
Stop! Light is red.
GREEN
Go! Light is green.
YELLOW
Caution! Light is yellow.
RED

Provalo tu

import 'traffic_light.dart';

void main() {
  // TODO: Crea un'istanza di TrafficLight
  
  // TODO: Stampa il colore iniziale
  
  // TODO: Chiama change() e stampa il colore (3 volte per attraversare tutti gli stati)
  // Primo cambio: RED -> GREEN
  
  // Secondo cambio: GREEN -> YELLOW
  
  // Terzo cambio: YELLOW -> RED
}
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 Dart online