Padrão de estado - State pattern

O padrão de estado é um padrão de design de software comportamental que permite a um objeto alterar seu comportamento quando seu estado interno muda. Esse padrão é próximo ao conceito de máquinas de estados finitos . O padrão de estado pode ser interpretado como um padrão de estratégia , que é capaz de mudar uma estratégia por meio de invocações de métodos definidos na interface do padrão.

O padrão de estado é usado em programação de computador para encapsular comportamentos variados para o mesmo objeto , com base em seu estado interno. Essa pode ser uma maneira mais limpa de um objeto alterar seu comportamento em tempo de execução sem recorrer a instruções condicionais e, assim, melhorar a capacidade de manutenção.

Visão geral

Um exemplo de classe UML e diagrama de sequência para o padrão de design State.

O padrão de design de estado é um dos vinte e três padrões de design documentados pela Gangue dos Quatro que descrevem como resolver problemas de design recorrentes. Esses problemas abrangem o projeto de software orientado a objetos flexível e reutilizável, como objetos que são fáceis de implementar, alterar, testar e reutilizar.

O padrão de estado é definido para resolver dois problemas principais:

  • Um objeto deve mudar seu comportamento quando seu estado interno muda.
  • O comportamento específico do estado deve ser definido de forma independente. Ou seja, adicionar novos estados não deve afetar o comportamento dos estados existentes.

Implementar o comportamento específico do estado diretamente dentro de uma classe é inflexível porque compromete a classe com um comportamento particular e torna impossível adicionar um novo estado ou alterar o comportamento de um estado existente posteriormente, independentemente da classe, sem alterar a classe. Neste, o padrão descreve duas soluções:

  • Defina objetos separados (estado) que encapsulam o comportamento específico de cada estado. Ou seja, defina uma interface (estado) para executar o comportamento específico do estado e defina as classes que implementam a interface para cada estado.
  • Uma classe delega o comportamento específico do estado para seu objeto de estado atual em vez de implementar o comportamento específico do estado diretamente.

Isso torna uma classe independente de como o comportamento específico do estado é implementado. Novos estados podem ser adicionados definindo novas classes de estado. Uma classe pode alterar seu comportamento em tempo de execução, alterando seu objeto de estado atual.


Estrutura

Estado em UML

No diagrama de classe UML ( Unified Modeling Language ) que acompanha , a classe não implementa o comportamento específico do estado diretamente. Em vez disso, refere-se à interface para executar o comportamento específico do estado ( ), o que torna independente de como o comportamento específico do estado é implementado. As classes e implementam a interface, ou seja, implementam (encapsulam) o comportamento específico de cada estado. O diagrama de sequência UML mostra as interações em tempo de execução: ContextContextStatestate.operation()ContextState1State2State

O Contextobjeto delega o comportamento específico do estado a diferentes Stateobjetos. Em primeiro lugar, Contextas chamadas operation(this)em seu atual (inicial) objeto de estado ( State1), que executa a operação e chamadas setState(State2)em Contextque o estado atual de contexto mudança State2. Na próxima vez, Contextchama novamente operation(this)seu objeto de estado atual ( State2), que executa a operação e altera o estado atual do contexto para State1.

Exemplo

Java

A interface de estado e duas implementações. O método do estado tem uma referência ao objeto de contexto e é capaz de alterar seu estado.

interface State {
    void writeName(StateContext context, String name);
}

class LowerCaseState implements State {
    @Override
    public void writeName(StateContext context, String name) {
        System.out.println(name.toLowerCase());
        context.setState(new MultipleUpperCaseState());
    }
}

class MultipleUpperCaseState implements State {
    /* Counter local to this state */
    private int count = 0;

    @Override
    public void writeName(StateContext context, String name) {
        System.out.println(name.toUpperCase());
        /* Change state after StateMultipleUpperCase's writeName() gets invoked twice */
        if (++count > 1) {
            context.setState(new LowerCaseState());
        }
    }
}

A classe de contexto possui uma variável de estado que ela instancia em um estado inicial, neste caso LowerCaseState. Em seu método, ele usa os métodos correspondentes do objeto de estado.

class StateContext {
    private State state;
    
    public StateContext() {
        state = new LowerCaseState();
    }

    /**
     * Set the current state.
     * Normally only called by classes implementing the State interface.
     * @param newState the new state of this context
     */
    void setState(State newState) {
        state = newState;
    }

    public void writeName(String name) {
        state.writeName(this, name);
    }
}

A demonstração abaixo mostra o uso:

public class StateDemo {
    public static void main(String[] args) {
        StateContext context = new StateContext();

        context.writeName("Monday");
        context.writeName("Tuesday");
        context.writeName("Wednesday");
        context.writeName("Thursday");
        context.writeName("Friday");
        context.writeName("Saturday");
        context.writeName("Sunday");
    }
}

Com o código acima, a saída main()de StateDemoé:

 monday
 TUESDAY
 WEDNESDAY
 thursday
 FRIDAY
 SATURDAY
 sunday

Referências