Playlist do Curso de Padrão de Projeto de Software (Design Patterns)
State é um padrão de projeto de software usado quando o comportamento de um objeto muda, dependendo do seu estado.
Introdução
Em certas ocasiões, quando o contexto em que está a desenvolver requer um objeto que possua comportamentos diferentes dependendo de qual estado se encontra, é difícil manejar a mudança de comportamento e os estados desse objeto, tudo dentro do mesmo bloco de código. O padrão State propõe uma solução para esta complicação, criando basicamente, um objeto para cada estado possível do objeto que o chama.
Objetivo
Permite que um objeto altere seu comportamento de acordo com o estado interno que se encontra em um momento dado.
Motivação
O padrão State é motivado por aqueles objetos que, em seu estado atual, varia o seu comportamento devido as diferentes mensagens que possa receber. Como exemplo, tomamos uma classe Livro, um objeto desta classe terá respostas diferentes, dependendo do seu estado(Disponível ou Emprestado). Por exemplo invocando o método reservar de um objeto da classe Livro seu comportamento será diferente, se o Livro está no estado Disponível ou no estado Emprestado.
Diagrama de Estados
No seguinte diagrama representamos os possíveis estados ou situações em que um Livro pode se encontrar no decorrer da execução em nosso sistema.
Diagrama de Estados em UML, ejemplo Padrão State
Problema
Há uma extrema complexidade no código quando tentamos gerênciar comportamentos diferentes, dependendo de um número de estados diferentes. Também manter o código torna-se difícil, e mesmo em alguns casos, podem apontar a uma inconsistência de estados atuais na forma de implementação dos diferentes estados no código (por exemplo, com variáveis para cada estado).
Estrutura UML
Os participantes
Contexto: Este integrante define a interface com o cliente. Mantém uma instância de Estado Concreto que define seu estado atual.
Estado: Define uma interface para encapsular as responsabilidades associadas a um estado particular de contexto.
Subclasse EstadoConcreto: Cada uma dessas subclasses implementa o comportamento ou responsabilidade de Contexto.
O Contexto delega o estado específico para o objeto EstadoConcreto atual. Um objeto de Contexto pode passar-se como parâmetro a um objeto Estado. Assim, a classe Estado pode acessar o contexto, se fosse necessário. Contexto é a interface principal para o cliente. O cliente pode configurar um contexto com objetos Estado. Uma vez feito isso, os clientes não têm de lidar com objetos de tipo Estado diretamente. Tanto o objeto de Contexto como os objetos de EstadoConcreto podem decidir a mudança de estado.
Colaborações
O padrão de State pode usar o padrão Singleton quando necessita a existência de apenas uma instância de cada estado. Se pode utilizar quando se compartem os objetos como Flyweight existindo uma única instância de cada Estado e esta é compartilhada com mais de um objeto.
Como funciona
A classe Contexto envia mensagens para os objetos de EstadoConcreto dentro de seu código para dar a estes a responsabilidade que deve ser cumprida pelo objeto Contexto. Então, o objeto Contexto vai mudando as responsabilidades de acordo com o estado em que se encontra, devido a que também muda de objeto EstadoConcreto ao fazer a mudança de estado.
Quando usá-lo?
Está recomendado quando um determinado objeto tem estados e responsabilidades diferentes, dependendo de qual estado você está em determinado momento. Também pode ser usada para simplificar os casos em que há código complicado e extenso de decisão que depende do estado do objeto
Vantagens e desvantagens
São as seguintes vantagens:
É fácil de localizar as responsabilidades de estados específicos, devido a que os encontram nas classes que correspondem a cada estado. Isto proporciona uma maior clareza no desenvolvimento e na manutenção subsequente. Esta facilidade é fornecida pelo fato de que diferentes estados são representados por um único atributo (estado) e não envolvidos em diferentes variáveis e grandes condicionais.
Faz as mudanças de estado explícitas, posto que em outro tipo de implantação os estados são alterados, modificando os valores em variáveis, enquanto aqui fazer-se representar cada estado.
Os objetos Estado podem ser compartilhados se eles não contêm variáveis de instância, isto pode ser alcançado se o estado está totalmente codificado representando seu tipo. Quando isso é feito, os estados são flyweights sem estado intrínseco.
Facilita a expansão de estados.
Permite a um objeto alterar de classe em tempo de execução dado que ao modificar suas responsabilidades pela de outro objeto de outra classe, a herança e responsabilidades do primeiro mudaram pelas do segundo.
Desvantagem:
Aumenta o número de subclasses.