Menu
Coddy logo textTech

Padrão State

Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 74 de 87.

O State Pattern é um padrão de projeto comportamental que permite que um objeto altere seu comportamento quando seu estado interno muda. O objeto parece mudar sua classe, mas, na realidade, ele delega o comportamento para diferentes objetos de estado. Pense em uma máquina de venda automática: sua resposta ao pressionar um botão depende se ela está ociosa, se tem dinheiro inserido ou se está dispensando um produto.

Em vez de usar instruções condicionais complexas para lidar com diferentes estados, você encapsula cada estado em sua própria classe. O padrão envolve um Context que mantém uma referência ao estado atual, e classes State que definem o comportamento para 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 o comportamento e pode disparar transições para outros 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());
    }
}

O contexto delega solicitações ao seu estado atual, e o comportamento muda automaticamente conforme o estado muda:

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

context.request();  // Inativo: Insira a moeda para começar
context.request();  // Ativo: Processando...

O Padrão State é ideal quando o comportamento de um objeto depende fortemente de seu estado e deve mudar em tempo de execução. Ele elimina grandes blocos condicionais e torna a adição de novos estados direta — basta criar uma nova classe que implemente a interface State.

challenge icon

Desafio

Fácil

Vamos construir um sistema de fluxo de trabalho de documentos usando o State Pattern! Você criará um sistema que modela como um documento se move através de diferentes estágios—Draft, Review e Published—com cada estado determinando quais ações estão disponíveis e como o documento se comporta quando você tenta editá-lo ou aprová-lo.

Você organizará seu código em quatro arquivos:

  • DocumentState.java: Defina a interface DocumentState que todos os estados implementarão. Ela deve declarar dois métodos: edit(Document doc) para tentar editar o documento, e approve(Document doc) para tentar aprovar/avançar o documento para o próximo estágio.
  • States.java: Crie três classes de estado concretas que implementam DocumentState:

    DraftState - Quando edit for chamado, imprima Editing draft.... Quando approve for chamado, imprima Draft approved. Moving to review. e mude o estado do documento para ReviewState.

    ReviewState - Quando edit for chamado, imprima Cannot edit during review. (sem mudança de estado). Quando approve for chamado, imprima Review complete. Publishing document. e mude para PublishedState.

    PublishedState - Quando edit for chamado, imprima Cannot edit published document.. Quando approve for chamado, imprima Document already published.. Nenhuma das ações altera o estado.

  • Document.java: Crie a classe de contexto que mantém o estado atual. Seu Document deve ter:

    Um campo privado que contém o DocumentState atual, inicializado como DraftState no construtor.

    Um método setState(DocumentState state) que altera o estado atual.

    Um método edit() que delega para o método edit do estado atual.

    Um método approve() que delega para o método approve do estado atual.

    Um método getStatus() que retorna o nome simples da classe do estado atual (use getClass().getSimpleName()).

  • Main.java: Demonstre seu sistema de estados! Você receberá uma entrada: uma sequência de ações como uma string separada por vírgulas, onde cada ação é edit ou approve (por exemplo: edit,approve,edit,approve).

    Crie um Document e imprima seu status inicial no formato Status: [state]. Em seguida, processe cada ação em ordem, chamando o método apropriado no documento. Após cada ação, imprima o status atual.

Você receberá uma entrada: uma string de ações separada por vírgulas.

Por exemplo, com a entrada edit,approve,approve, sua saída seria:

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

Observe como a mesma chamada approve() produz resultados diferentes dependendo do estado atual do documento—esta é a essência do State Pattern! O documento não usa condicionais para verificar seu estado; em vez disso, ele delega o comportamento ao objeto de estado atual, que lida com a ação apropriadamente e aciona transições quando necessário.

Folha de consulta

O State Pattern é um padrão de projeto comportamental que permite que um objeto altere seu comportamento quando seu estado interno muda, delegando o comportamento para diferentes objetos de estado em vez de usar instruções condicionais complexas.

O padrão consiste em um Context que mantém uma referência ao estado atual, e classes State que definem o comportamento para 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 o comportamento e pode disparar transições para outros 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());
    }
}

O contexto delega as solicitações ao seu estado atual, e o comportamento muda automaticamente conforme o estado se altera:

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

context.request();  // Idle: Insert coin to start
context.request();  // Active: Processing...

O State Pattern é ideal quando o comportamento de um objeto depende fortemente de seu estado e deve mudar em tempo de execução. Ele elimina grandes blocos condicionais e torna a adição de novos estados algo simples.

Experimente você mesmo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        
        // TODO: Criar um novo Document
        
        // TODO: Imprimir o status inicial no formato "Status: [state]"
        
        // TODO: Dividir a entrada por vírgula para obter as ações individuais
        
        // TODO: Percorrer cada ação
        // - Se a ação for "edit", chamar edit() no document
        // - Se a ação for "approve", chamar approve() no document
        // - Após cada ação, imprimir o status atual
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos