Menu
Coddy logo textTech

Patrón State

Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy. Lección 74 de 87.

El patrón State es un patrón de diseño de comportamiento que permite que un objeto cambie su comportamiento cuando cambia su estado interno. El objeto parece cambiar de clase, pero en realidad delega el comportamiento en distintos objetos de estado. Piensa en una máquina expendedora: su respuesta al pulsar un botón depende de si está inactiva, tiene dinero insertado o está dispensando un producto.

En lugar de usar instrucciones condicionales complejas para gestionar diferentes estados, encapsulas cada estado en su propia clase. El patrón implica un Contexto que mantiene una referencia al estado actual y clases State que definen el comportamiento de cada estado:

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);
    }
}

Cada estado concreto implementa el comportamiento y puede activar transiciones a otros estados:

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());
    }
}

El contexto delega las solicitudes a su estado actual, y el comportamiento cambia automáticamente a medida que cambia el estado:

Context context = new Context();
context.setState(new IdleState());

context.request();  // Idle: Inserta una moneda para empezar
context.request();  // Active: Procesando...

El patrón State es ideal cuando el comportamiento de un objeto depende en gran medida de su estado y debe cambiar durante la ejecución. Elimina grandes bloques condicionales y facilita la adición de nuevos estados; solo tienes que crear una nueva clase que implemente la interfaz State.

challenge icon

Desafío

Fácil

¡Construyamos un sistema de flujo de trabajo de documentos usando el patrón State! Crearás un sistema que modela cómo un documento pasa por distintas etapas, Draft, Review y Published, donde cada estado determina qué acciones están disponibles y cómo se comporta el documento cuando intentas editarlo o aprobarlo.

Organizarás tu código en cuatro archivos:

  • DocumentState.java: Define la interfaz DocumentState que implementarán todos los estados. Debe declarar dos métodos: edit(Document doc) para intentar editar el documento y approve(Document doc) para intentar aprobarlo o avanzarlo a la siguiente etapa.
  • States.java: Crea tres clases de estado concretas que implementen DocumentState:

    DraftState: cuando se llama a edit, imprime Editing draft.... Cuando se llama a approve, imprime Draft approved. Moving to review. y cambia el documento al estado ReviewState.

    ReviewState: cuando se llama a edit, imprime Cannot edit during review. (no cambia el estado). Cuando se llama a approve, imprime Review complete. Publishing document. y cambia al estado PublishedState.

    PublishedState: cuando se llama a edit, imprime Cannot edit published document.. Cuando se llama a approve, imprime Document already published.. Ninguna de las dos acciones cambia el estado.

  • Document.java: Crea la clase de contexto que mantiene el estado actual. Tu Document debe tener:

    Un campo privado que contenga el DocumentState actual, inicializado en DraftState dentro del constructor.

    Un método setState(DocumentState state) que cambie el estado actual.

    Un método edit() que delegue en el método edit del estado actual.

    Un método approve() que delegue en el método approve del estado actual.

    Un método getStatus() que devuelva el nombre simple de la clase del estado actual (usa getClass().getSimpleName()).

  • Main.java: ¡Demuestra tu sistema de estados! Recibirás una entrada: una secuencia de acciones en forma de cadena separada por comas, donde cada acción es edit o approve (por ejemplo: edit,approve,edit,approve).

    Crea un Document e imprime su estado inicial con el formato Status: [state]. Después, procesa cada acción en orden y llama al método correspondiente del documento. Después de cada acción, imprime el estado actual.

Recibirás una entrada: una cadena de acciones separadas por comas.

Por ejemplo, con la entrada edit,approve,approve, el resultado sería:

Status: DraftState
Editing draft...
Status: DraftState
Draft approved. Moving to review.
Status: ReviewState
Review complete. Publishing document.
Status: PublishedState

Observa cómo la misma llamada a approve() produce resultados diferentes según el estado actual del documento. ¡Esta es la esencia del patrón State! El documento no usa condicionales para comprobar su estado; en su lugar, delega el comportamiento en el objeto de estado actual, que gestiona la acción adecuadamente y activa las transiciones cuando es necesario.

Pruébalo tú mismo

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 nuevo Document
        
        // TODO: Imprime el estado inicial en formato "Status: [state]"
        
        // TODO: Divide la entrada por comas para obtener las acciones individuales
        
        // TODO: Recorre cada acción
        // - Si la acción es "edit", llama a edit() en document
        // - Si la acción es "approve", llama a approve() en document
        // - Después de cada acción, imprime el estado actual
    }
}
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

Practica por tu cuenta: Compilador de Java online