Série DesignPattern:State

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

2 comentários em “Série DesignPattern:State”

  1. 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

    1. 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

Deixe um comentário

O seu endereço de e-mail não será publicado.