Olá Pessoal,
No post de hoje vamos conhecer o design pattern chamado State. Em poucas palavras, ele é baseado no comportamento do objeto. Se o comportamento foi alterado para Y, então a forma de trabalho desse objeto é Y. Vamos ver colocando à mão na massa, acho que será mais produtivo.
Lets go…
Download dos projetos
https://github.com/camilolopes
State
É um padrão comportamental do design pattern. Este é focado em saber se o estado de um objeto foi alterado. Ou seja, o State permite alterar o comportamento de um objeto com base no estado atual.
Se o taxímetro é bandeira 1, o cálculo é feito de maneira X, com valores Y, mas se o estado atual saiu de bandeira 1 e foi para bandeira 2, o cálculo é feito de maneira X com valor Z.
No diagrama que criei acima mostra como as classes se entendem.
Na Prática
Agora vamos conhecer praticando, e como sempre, código no modo didático para ajudar quem está vendo o assunto pela primeira vez. A seguir, nosso projeto:
Bandeira.java
Criaremos inicialmente a interface state, que é a Bandeira.
Bandeira.java
package br.com.camilolopes.interfaces.state;
public interface Bandeira {
double calculoBandeira(double distancia);
}
As classes Bandeira 1, Bandeira2.java são classes que implementam o State, ou seja, Bandeira 1 tem uma formula X de cálculo, a bandeira 2 também terá a forma dele calcular e assim sucessivamente.
package br.com.camilolopes.classes;
import br.com.camilolopes.interfaces.state.Bandeira;
public class Bandeira1 implements Bandeira {
@Override
public double calculoBandeira(double distancia) {
double total = distancia * 1.5 ;
return total;
}
}
Bandeira2.java
package br.com.camilolopes.classes;
import br.com.camilolopes.interfaces.state.Bandeira;
public class Bandeira2 implements Bandeira {
@Override
public double calculoBandeira(double distancia) {
//não gosto muito desses number magic aqui, mas vou deixar por enquanto
double total = distancia * 3.0 + 1.0;
return total;
}
}
Taximetro.java
package br.com.camilolopes.classes;
import br.com.camilolopes.interfaces.state.Bandeira;
/*
* classe que mantem referencia para um State com base no estado atual
*/
public class Taximetro {
/*um taximetro has-a bandeira
* ou seja, para um taximetro ter vida
* ele precisa estar associado com uma bandeira
*/
private Bandeira bandeira;public Taximetro(Bandeira bandeira) {
super();
this.bandeira = bandeira;
}public Bandeira getBandeira() {
return bandeira;
}public void setBandeira(Bandeira bandeira) {
this.bandeira = bandeira;
}
//aqui o taximetro vai calcular c/ base no tipo de Bandeira
public double calculaCorrida(double distancia){
double totalCorrida = bandeira.calculoBandeira(distancia);
return totalCorrida;
}
}
Criamos o relacionamento entre o Taxímetro e a Bandeira, já que para o taxímetro existir precisa de uma bandeira.
TaximetroMain.java
import br.com.camilolopes.classes.Bandeira1;
import br.com.camilolopes.classes.Bandeira2;
import br.com.camilolopes.classes.Taximetro;public class TaxiMain {
public static void main(String[] args) {
Bandeira1 bandeira1 = new Bandeira1();
Taximetro taximetro = new Taximetro(bandeira1);
taximetro.setBandeira(bandeira1);
System.out.println(“Valor da corrida com bandeira 1: “+ taximetro.calculaCorrida(2.0));
taximetro.setBandeira(new Bandeira2());
System.out.println(“O valor da corrida com bandeira 2: ” + taximetro.calculaCorrida(2.0));
}
}
Feito isso, criamos uma classe main que vai nos ajudar a ver o resultado com base no tipo passado.
Resultado
A seguir temos o resultado com a Bandeira 1 e 2. Observe que a distância passada foi a mesma, porém o resultado diferente, já que cada Bandeira tem um cálculo específico e o nosso Taxímetro sabe o que mostrar com base no estado da Bandeira (1,2,3…)
E esse é o design pattern state. Vou ficando por aqui e até o próximo post.
See ya!!
Olá Camilo, acredito que o seu exemplo de State não seja muito bom, pois ele está demonstrando como implementar o padrão Strategy.
Veja que os padrões State e Strategy são praticamente identicos, a diferença básica é que com o padrão Strategy, o cliente decide qual estratégia usar, como você demonstrou no exemplo, já no padrão State, o objeto modifica seu comportamento baseado na mudança do seu estado interno, por exemplo, se for feriado o taxímetro automaticamente modifica seu estado interno para Bandeira2.
Não sei se fui bastante claro.
Abraços
olá Fabricio,
Sim você está certo. E no exemplo, não é o “taxista” que diz qual estratégia usar, e sim o taximetro já faz os cálculos com base na bandeira, o que mostrei na classe main, é como o taximetro se comporta e faz os cálculos de acordo com a bandeira. Mas, não há envolvimento do cliente nesse caso.
abraços