O padrão State é um padrão de design comportamental que tem como objetivo principal permitir que um objeto altere seu comportamento quando o seu estado interno muda. O padrão State resolve uma série de problemas relacionados ao gerenciamento de estados e comportamentos em sistemas orientados a objetos:

  1. Eliminação de Condicionais Complexas: Em sistemas onde o comportamento de um objeto depende de seu estado e existe uma complexa estrutura condicional (if ou switch) para controlar essas mudanças, o padrão State encapsula os comportamentos associados a cada estado em classes separadas, simplificando assim o código e tornando-o mais fácil de manter.

  2. Encapsulamento do Estado Específico: Ao separar os comportamentos específicos de cada estado em classes diferentes, o padrão State promove um melhor encapsulamento e organiza o código de forma mais clara.

  3. Transições de Estado Facilitadas: Facilita a transição entre estados, já que as mudanças de estado implicam na substituição de um objeto de estado por outro, ao invés de alterar muitos atributos internos.

  4. Extensibilidade: Novos estados e comportamentos podem ser adicionados facilmente sem alterar os estados existentes, tornando o sistema mais extensível.

Como Funciona

O padrão State envolve geralmente três componentes principais:

  • Contexto: Classe que possui um estado atual. Ela mantém uma referência a um objeto de estado que representa seu estado atual e delega as solicitações de comportamento para esse objeto.
  • State (Interface ou Classe Abstrata): Define uma interface para encapsular o comportamento associado a um determinado estado do Contexto.
  • Concrete States: Classes que implementam a interface State. Cada classe representa um estado específico do Contexto e contém o comportamento específico para esse estado.

Exemplo

Um exemplo clássico do uso do padrão State é em uma máquina de venda automática ou em um jogo, onde o objeto pode ter estados como 'sem moeda', 'com moeda', 'item selecionado', etc. Cada estado tem comportamentos diferentes (por exemplo, inserir moeda, selecionar item, entregar item) e o objeto muda seu comportamento de acordo com o estado atual.

Exemplo de Implementação

Vamos criar um exemplo simples do padrão State em Java. Vamos desenvolver um sistema básico para um semáforo que altera seu estado entre verde, amarelo e vermelho.

Interface State

Primeiro, definimos a interface State, que será implementada por todos os estados:

public interface State {
    void handle(Semaforo semaforo);
}

Estados Concretos

Implementamos os estados concretos para o semáforo:

public class Verde implements State {
    @Override
    public void handle(Semaforo semaforo) {
        System.out.println("Luz verde: Pode passar");
        semaforo.setState(new Amarelo());
    }
}
 
public class Amarelo implements State {
    @Override
    public void handle(Semaforo semaforo) {
        System.out.println("Luz amarela: Atenção");
        semaforo.setState(new Vermelho());
    }
}
 
public class Vermelho implements State {
    @Override
    public void handle(Semaforo semaforo) {
        System.out.println("Luz vermelha: Pare");
        semaforo.setState(new Verde());
    }
}

Contexto

Agora, criamos a classe Semaforo que é o contexto. Ela mantém uma referência ao estado atual e permite sua mudança:

public class Semaforo {
    private State estadoAtual;
 
    public Semaforo(State estadoInicial) {
        this.estadoAtual = estadoInicial;
    }
 
    public void setState(State estado) {
        this.estadoAtual = estado;
    }
 
    public void change() {
        estadoAtual.handle(this);
    }
}

Testando o Padrão State

Por fim, usamos o padrão State para controlar o semáforo:

public class Main {
    public static void main(String[] args) {
        Semaforo semaforo = new Semaforo(new Verde());
 
        // Estado inicial: Verde
        semaforo.change(); // Muda para Amarelo
 
        // Estado atual: Amarelo
        semaforo.change(); // Muda para Vermelho
 
        // Estado atual: Vermelho
        semaforo.change(); // Muda para Verde novamente
    }
}
 

Neste exemplo, a classe Semaforo é configurada com um estado inicial (Verde) e a cada chamada do método change(), o estado do semáforo muda e o comportamento associado a esse estado é executado. Isso demonstra como o padrão State permite a um objeto mudar seu comportamento dinamicamente de acordo com seu estado interno, mantendo o código organizado e facilitando a adição de novos estados.

Padrão State e State Machine

O padrão State é uma forma de implementar uma máquina de estados em um contexto de programação orientada a objetos, focando na maneira como o comportamento de um objeto pode ser alterado dinamicamente conforme ele muda de estado. As máquinas de estados, por outro lado, são um conceito mais amplo e podem ser implementadas de várias maneiras, dependendo do contexto e das necessidades específicas do sistema.