Seções iMasters
Desenvolvimento + Java

Design Pattern não é receita de bolo – Parte 03: State

Hoje veremos 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 a mão na massa, acho que será mais produtivo.

Let’s go…

State

É um padrão comportamental do design pattern. Ele é 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.

O diagrama 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.

package br.com.camilolopes.interfaces.state;

public interface Bandeira {
double calculoBandeira(double distancia);
}

BandeiraXX.java

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;
}

}

Bandeira 2.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;
}

}

Taxímetro.java

Criamos o relacionamento entre o Taxímetro e a Bandeira, já que para o taxímetro existir é necessária uma bandeira.

package br.com.camilolopes.classes;

import br.com.camilolopes.interfaces.state.Bandeira;
/*
* classe que mantém 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;
}
}

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!!

Comente também

7 Comentários

Priss Guerrero

Descobri essa série de artigos sobre Design Patterns por esta parte 03, no Twitter. Vou continuar acompanhando. A postagem é semanal?

Você é bem didático, muito grata. Sou iniciante e tenho um certo bloqueio com o Java, rs. Vou praticar seus posts neste final de semana.

Você utiliza o Eclipse?

Ah, por favor, por que em alguns trechos você utiliza ? Eu já li sobre o que seria isso, mas não recordo. Você está indicando que é uma herança, seria isso?

Desculpe mesmo se disse muita abobrinha, mas como disse sou iniciante e também quero aprender, por isso que perguntei algo tão banal, não se ofenda.

Grata.

    victor neves

    “Para fazermos uma classe herdar as características de uma outra, usamos a palavra reservada extends logo após a definicação do nome da classe. Dessa forma:

    class NomeDaClasseASerCriada extends NomeDaClasseASerHerdada

    Importante: Java permite que uma classe herde apenas as características de uma única classe, ou seja, não pode haver heranças múltiplas. Porém, é permitido heranças em cadeias, por exemplo: se a classe Mamifero herda a classe Animal, quando fizermos a classe Cachorro herdar a classe Mamifero, a classe Cachorro também herdará as características da classe Animal.
    Como estamos tratando de herança de classes, toda classe tem seu método construtor. Portanto, se estamos trabalhando com duas classes, temos dois métodos construtores. Para acessarmos o método construtor da classe que está sendo herdada usamos o super().”

victor neves

“Taximetro taximetro = new Taximetro(bandeira1);
taximetro.setBandeira(bandeira1); ”
??? voce não está repetindo uma ação? já que voce passou “bandeira1″ por construtor não teria a necessidade de voce passar novamente por set! teria????

Johnny Willer

No construtor da classe Taximetro você usou a palavra super(), mas qual o propósito dela aí? pois até o ponto que sei ele só é usado quando a classe herda caracteristicas de outra.
Ainda nao compreendo muito bem o Java, entao desculpe se minha dúvida parecer estúpida

Camilo Lopes

Victor,
Realmente não tem necessidade. É que estava pensando em outro exemplo que estava fazendo com o mesmo cenário e não removi a linha. Vocês está certo.

Johnny,
O construtor padrão foi sobrecarregado, toda classe java extends Object, então vc precisa chamar o construtor default da classe pai a partir do construtor sobrecarregado. Pois, a chamada não é feita de forma implicita nesse caso.

Priss ,
Tem haver com herança sim. Respondi acima.

Henrique

Olha, pra mim isso está mais pra Strategy que State…

Rodrigo

Pra mim isso é polimorfismo simples.

Qual a sua opinião?