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.
Desafio
FácilVamos 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 interfaceDocumentStateque todos os estados implementarão. Ela deve declarar dois métodos:edit(Document doc)para tentar editar o documento eapprove(Document doc)para tentar aprovar/avançar o documento para a próxima etapa.States.java: Crie três classes de estado concretas que implementemDocumentState:DraftState- Quandoeditfor chamado, imprimaEditing draft.... Quandoapprovefor chamado, imprimaDraft approved. Moving to review.e faça a transição do documento paraReviewState.ReviewState- Quandoeditfor chamado, imprimaCannot edit during review.(sem alteração de estado). Quandoapprovefor chamado, imprimaReview complete. Publishing document.e faça a transição paraPublishedState.PublishedState- Quandoeditfor chamado, imprimaCannot edit published document.. Quandoapprovefor chamado, imprimaDocument already published.. Nenhuma das ações altera o estado.Document.java: Crie a classe de contexto que mantém o estado atual. SeuDocumentdeve ter:Um campo privado que armazena o
DocumentStateatual, inicializado comoDraftStateno construtor.Um método
setState(DocumentState state)que altera o estado atual.Um método
edit()que delega ao métodoeditdo estado atual.Um método
approve()que delega ao métodoapprovedo estado atual.Um método
getStatus()que retorna o nome simples da classe do estado atual (usegetClass().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 éeditouapprove(por exemplo:edit,approve,edit,approve).Crie um
Documente imprima seu status inicial no formatoStatus: [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: PublishedStateObserve 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
}
}
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
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão IteratorPratique por conta própria: Compilador de Java online