Padrão de Estado em Java: Uma Abordagem Detalhada

Conceito do Padrão de Estado

O padrão de estado é um design pattern comportamental que permite que um objeto modifique seu comportamento quando seu estado interno muda. Em vez de usar uma série de instruções condicionais para definir o comportamento, cada estado é encapsulado em uma clase separada, e o objeto delega as operações para o estado atual. Isso torna o código mais limpo e fácil de manter.

Estrutura do Padrão de Estado

A estrutura do padrão de estado envolve três componentes principais:

  • Contexto (Context): Mantém uma referência ao objeto de estado atual e delega as solicitações para esse objeto.
  • Estado (State): Define uma interface comum para todos os estados possíveis.
  • Estado Concreto (ConcreteState): Implementa a interface de estado para um estado específico.

Exemplo em Java: Máquina de Venda Automática

Vamos implementar uma máquina de venda automática usando o padrão de estado. A máquina pode estar em diferentes estados: sem moeda, com moeda, vendendo e sem estoque.

Definição da Interface Estado


public interface Situacao {
    void inserirMoeda();
    void devolverMoeda();
    void girarManivela();
    void dispensarItem();
}

Implementação dos Estados Concretos

SemMoedaState


public class SemMoedaState implements Situacao {
    private MaquinaDeVenda maquina;

    public SemMoedaState(MaquinaDeVenda maquina) {
        this.maquina = maquina;
    }

    public void inserirMoeda() {
        System.out.println("Você inseriu uma moeda.");
        maquina.setEstado(maquina.getComMoedaState());
    }

    public void devolverMoeda() {
        System.out.println("Não há moeda para devolver.");
    }

    public void girarManivela() {
        System.out.println("Insira uma moeda primeiro.");
    }

    public void dispensarItem() {
        System.out.println("Por favor, insira uma moeda.");
    }
}

ComMoedaState


public class ComMoedaState implements Situacao {
    private MaquinaDeVenda maquina;

    public ComMoedaState(MaquinaDeVenda maquina) {
        this.maquina = maquina;
    }

    public void inserirMoeda() {
        System.out.println("Já há uma moeda inserida.");
    }

    public void devolverMoeda() {
        System.out.println("Moeda devolvida.");
        maquina.setEstado(maquina.getSemMoedaState());
    }

    public void girarManivela() {
        System.out.println("Você girou a manivela.");
        maquina.setEstado(maquina.getVendendoState());
        maquina.dispensarItem();
    }

    public void dispensarItem() {
        System.out.println("Nenhum item disponível para dispensar.");
    }
}

VendendoState


public class VendendoState implements Situacao {
    private MaquinaDeVenda maquina;

    public VendendoState(MaquinaDeVenda maquina) {
        this.maquina = maquina;
    }

    public void inserirMoeda() {
        System.out.println("Aguarde, já estamos processando sua compra.");
    }

    public void devolverMoeda() {
        System.out.println("Não pode devolver a moeda, já girou a manivela.");
    }

    public void girarManivela() {
        System.out.println("Girar duas vezes não resulta em dois itens.");
    }

    public void dispensarItem() {
        maquina.liberarItem();
        if (maquina.getQuantidade() > 0) {
            maquina.setEstado(maquina.getSemMoedaState());
        } else {
            System.out.println("Ops, sem estoque!");
            maquina.setEstado(maquina.getSemEstoqueState());
        }
    }
}

SemEstoqueState


public class SemEstoqueState implements Situacao {
    private MaquinaDeVenda maquina;

    public SemEstoqueState(MaquinaDeVenda maquina) {
        this.maquina = maquina;
    }

    public void inserirMoeda() {
        System.out.println("Não pode inserir moedas, a máquina está sem estoque.");
    }

    public void devolverMoeda() {
        System.out.println("Não pode devolver moedas, nenhuma foi inserida.");
    }

    public void girarManivela() {
        System.out.println("Girou a manivela, mas não há itens disponíveis.");
    }

    public void dispensarItem() {
        System.out.println("Nenhum item disponível para dispensar.");
    }
}

Classe Contexto


public class MaquinaDeVenda {
    Situacao semMoedaState;
    Situacao comMoedaState;
    Situacao vendendoState;
    Situacao semEstoqueState;

    Situacao estadoAtual;
    int quantidade = 0;

    public MaquinaDeVenda(int quantidade) {
        this.quantidade = quantidade;
        semMoedaState = new SemMoedaState(this);
        comMoedaState = new ComMoedaState(this);
        vendendoState = new VendendoState(this);
        semEstoqueState = new SemEstoqueState(this);

        if (quantidade > 0) {
            estadoAtual = semMoedaState;
        } else {
            estadoAtual = semEstoqueState;
        }
    }

    public void inserirMoeda() {
        estadoAtual.inserirMoeda();
    }

    public void devolverMoeda() {
        estadoAtual.devolverMoeda();
    }

    public void girarManivela() {
        estadoAtual.girarManivela();
        estadoAtual.dispensarItem();
    }

    void setEstado(Situacao estado) {
        estadoAtual = estado;
    }

    void liberarItem() {
        System.out.println("Um item está sendo dispensado...");
        if (quantidade > 0) {
            quantidade--;
        }
    }

    public Situacao getSemMoedaState() {
        return semMoedaState;
    }

    public Situacao getComMoedaState() {
        return comMoedaState;
    }

    public Situacao getVendendoState() {
        return vendendoState;
    }

    public Situacao getSemEstoqueState() {
        return semEstoqueState;
    }

    public int getQuantidade() {
        return quantidade;
    }
}

Teste da Máquina de Venda Automática


public class TesteMaquinaDeVenda {
    public static void main(String[] args) {
        MaquinaDeVenda maquina = new MaquinaDeVenda(5);

        maquina.inserirMoeda();
        maquina.girarManivela();
        maquina.devolverMoeda();
        maquina.inserirMoeda();
        maquina.inserirMoeda();
        maquina.girarManivela();

        for (int i = 0; i < 6; i++) {
            maquina.girarManivela();
        }
    }
}

Vantagens e Desvantagens

Vantagens

  • Lógica Clara: Cada estado tem sua própria lógica, eliminando a necessidade de muitas estruturas condicionais.
  • Extensibilidade: Novos estados podem ser adicionados facilmente sem modificar a clase de contexto.
  • Mantenibilidade: Alterações em um estado não afetam outros estados.

Desvantagens

  • Aumento de Classes: Cada estado requer uma nova classe, aumentando a complexidade.
  • Complexidade de Transição: Gerenciar transições entre estados pode se tornar complicado.

Casos de Uso

  • Sistemas de Workflow: Gestão de tarefas em diferentes estágios.
  • Jogos: Controle de ações de personagens e cenários.
  • Dispositivos Eletrônicoss: Gerenciamento de estados de dispositivos como impressoras e roteadores.

Tags: java state-pattern design-patterns object-oriented-programming

Publicado em 8-9 09:32