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 padrão State é um padrão comportamental de projeto que permite que um objeto altere seu comportamento quando seu estado interno muda. O objeto parece mudar de classe, mas, na realidade, ele delega o comportamento a diferentes objetos de estado. Pense em uma máquina de venda automática: sua resposta ao pressionar um botão depende de ela estar ociosa, ter dinheiro inserido ou estar liberando 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 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 o comportamento e pode acionar 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 muda:

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

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

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

challenge icon

Desafio

Fácil

Vamos criar um sistema de fluxo de trabalho de documentos usando o Padrão de Estado! Você criará um sistema que modela como um documento passa por diferentes etapas: Rascunho, Revisão e Publicado, 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 a próxima etapa.
  • States.java: Crie três classes de estado concretas que implementem DocumentState:

    DraftState - Quando edit for chamado, imprima Editing draft.... Quando approve for chamado, imprima Draft approved. Moving to review. e faça a transição do documento para ReviewState.

    ReviewState - Quando edit for chamado, imprima Cannot edit during review. (sem alteração de estado). Quando approve for chamado, imprima Review complete. Publishing document. e faça a transição 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 armazena 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 ao método edit do estado atual.

    Um método approve() que delega ao 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, em que 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 na 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 separadas 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. Essa é a essência do Padrão de Estado! O documento não usa condicionais para verificar seu estado; em vez disso, ele delega o comportamento ao objeto de estado atual, que lida adequadamente com a ação e aciona as transições quando necessário.

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: Crie um novo Document
        
        // TODO: Imprima o status inicial no formato "Status: [state]"
        
        // TODO: Divida a entrada por vírgula para obter as ações individuais
        
        // TODO: Percorra cada ação
        // - Se a ação for "edit", chame edit() no document
        // - Se a ação for "approve", chame approve() no document
        // - Após cada ação, imprima 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

Pratique por conta própria: Compilador de Java online