Menu
Coddy logo textTech

Patrón State

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 98 de 110.

El patrón State permite que un objeto cambie su comportamiento cuando cambia su estado interno, haciendo que parezca como si el objeto hubiera cambiado de clase. En lugar de utilizar condicionales complejos para manejar diferentes estados, encapsulas cada estado en su propia clase y delegas el comportamiento al objeto de estado actual.

El patrón consiste en un Context que mantiene una referencia al estado actual, y clases State que definen el comportamiento para cada estado posible. Cuando el estado del contexto cambia, su comportamiento cambia automáticamente:

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());  // Borrador (Draft)
  doc.publish();           // Pasando a revisión... (Moving to review...)
  print(doc.getStatus());  // En revisión (Under Review)
  doc.publish();           // ¡Documento publicado! (Document published!)
  print(doc.getStatus());  // Publicado (Published)
}

Cada clase de estado maneja la acción publish() de manera diferente y puede realizar la transición del documento al siguiente estado. La clase Document no necesita condicionales para verificar su estado actual; simplemente delega en cualquier objeto de estado que esté activo en ese momento. Este patrón es ideal para objetos con distintos modos de comportamiento, como el procesamiento de pedidos, reproductores multimedia o sistemas de flujo de trabajo.

challenge icon

Desafío

Fácil

¡Vamos a construir un sistema de semáforo utilizando el patrón State! Crearás un semáforo que cicla a través de diferentes estados, donde cada estado determina el color de la luz y cómo transiciona al siguiente estado.

Organizarás tu código en dos archivos:

  • traffic_light.dart: Este archivo contiene tus clases de estado y el contexto del semáforo. Crea una clase abstracta TrafficLightState con dos métodos: String getColor() que devuelve el color actual de la luz, y void next(TrafficLight light) que transiciona el semáforo a su siguiente estado. Implementa tres clases de estado concretas:
    • RedState - devuelve RED como su color e imprime Stop! Light is red. cuando se llama a next(), luego transiciona a GreenState
    • GreenState - devuelve GREEN como su color e imprime Go! Light is green. cuando se llama a next(), luego transiciona a YellowState
    • YellowState - devuelve YELLOW como su color e imprime Caution! Light is yellow. cuando se llama a next(), luego transiciona a RedState
    Luego crea una clase TrafficLight (el contexto) que comience en RedState. Debe tener un método setState() para cambiar el estado actual, un método getColor() que delegue en el estado actual, y un método change() que llame a next() en el estado actual.
  • main.dart: Importa tu archivo de semáforo y demuestra el patrón State en acción. Crea un TrafficLight e imprime su color inicial. Luego llama a change() tres veces, imprimiendo el color después de cada cambio. Esto mostrará el semáforo ciclando a través de todos los estados y volviendo al principio.

¡Observa cómo la clase TrafficLight no necesita condicionales para determinar el comportamiento - cada estado conoce su propio color y qué estado sigue! ¡El semáforo simplemente delega en cualquier estado que esté activo actualmente!

Salida esperada:

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

Hoja de referencia

El patrón State permite que un objeto cambie su comportamiento cuando cambia su estado interno. En lugar de utilizar condicionales complejos, cada estado se encapsula en su propia clase.

El patrón consta de:

  • Contexto: Mantiene una referencia al estado actual
  • Clases de estado: Definen el comportamiento para cada estado posible

Estructura básica:

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 Document {
  DocumentState _state = DraftState();

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

El contexto delega el comportamiento al objeto de estado actual. Cada clase de estado maneja las acciones de manera diferente y puede realizar la transición al siguiente estado. Esto elimina la necesidad de condicionales para verificar el estado actual.

Ideal para objetos con distintos modos de comportamiento, como el procesamiento de pedidos, reproductores multimedia o sistemas de flujo de trabajo.

Pruébalo tú mismo

import 'traffic_light.dart';

void main() {
  // TODO: Crear una instancia de TrafficLight
  
  // TODO: Imprimir el color inicial
  
  // TODO: Llamar a change() e imprimir el color (3 veces para recorrer todos los estados)
  // Primer cambio: RED -> GREEN
  
  // Segundo cambio: GREEN -> YELLOW
  
  // Tercer cambio: YELLOW -> RED
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos