O padrão de projeto State é um padrão Comportamental que, às vezes, também é chamado de padrão de objetos para estados. Nesse padrão, um objeto pode encapsular vários comportamentos de acordo com o seu estado interno. Um padrão State também é considerado como uma maneira de um objeto alterar o seu comportamento em tempo de execução. Ele é usado para desenvolver Máquinas de Estado Finitas (Finite State Machines) e ajuda a acomodar Ações de Transição de Estados (State Transition Actions), utilizando três participantes principais:
State
: é considerada uma interface que encapsula o comportamento do objeto. Esse comportamento está associado ao estado do objeto.ConcreteState
: é uma subclasse que implementa a interface State. ConcreteState implementa o comportamento propriamente dito associado ao estado particular do objeto.Context
: define a interface de interesse dos clientes. Context também mantém uma instância da subclasse ConcreteState que, internamente, define a implementação do estado particular do objeto.
O exemplo de código a seguir serve para compreender o padrão com todos os participantes envolvidos. Definimos uma interface State que tem um método abstrato Handle()
. As classes ConcreteState
– ConcreteStateA
e ConcreteStateB
– implementam a interface State e, desse modo, definem os métodos Handle()
específicos das classes ConcreteState. Então, quando a classe Context é definida para um estado, o método Handle()
da ConcreteClass desse estado é chamado. No exemplo a seguir, como Context é definido com stateA, o método ConcreteStateA.Handle()
é chamado e exibe ConcreteStateA.
Suponha que queremos implementar um controle remoto de TV com um botão simples para realizar ações de ligar/desligar. Se a TV estiver ligada, o botão do controle remoto desligará a TV e vice-versa. Nesse caso, a interface State definirá o método (por exemplo, doThis()
) para executar ações como ligar/desligar a TV. Também precisamos definir ConcreteClass para estados diferentes. Nesse exemplo, temos dois estados principais, StartState
e StopState
, que indicam quando a TV está ligada e o estado em que ela está desligada, respectivamente. Para esse cenário, a classe TVContext
implementará a interface State e manterá uma referência ao estado atual. Com base na requisição, TVContext a encaminha para ConcreteState, que implementa o comportamento propriamente dito (para um dado estado) e executa a ação necessária. Então, nesse caso, o estado-base é StartState
(conforme definido anteriormente) e a requisição recebida pela classe TVContext
é desligar a TV. A classe TVContext compreende a necessidade e, de acordo com ela, encaminha a requisição para a classe concreta StopState
, que, por sua vez, chama o método doThis()
para desligar a TV: