Olá Pessoal,
Chegamos ao último post da Série DesignPattern. E hoje vamos conhecer o padrão de comportamento Visitor. Em resumo, o Visitor permite atualizarmos uma coleção de objetos de acordo com o tipo de cada objeto contido na coleção. Na prática você tem uma lista com vários objetos com tipos diferentes e cada um sofrerá um tipo de atualização. Neste post vamos ver isso, praticando com o conceito de contas bancárias.
Lets go…
Visitor
Permite atualizações específicas em uma coleção de objetos de acordo com o tipo particular de cada objeto.
Exemplo: posso ter uma lista de contas: poupança, corrente, digital etc. O banco pode querer atualizar a taxa para o valor X com base no tipo. Se for poupança, a taxa de rendimento será 0.5%, se for corrente será 0.0%. No diagrama a seguir temos uma ideia do Visitor. Fiz com base no nosso exemplo.
Praticando
A seguir teremos o projeto e a implementação. Como sempre, há comentários chamando atenção para o que considerei importante. Crie um projeto conforme a imagem seguir:
Criando o Visitor AtualizadorConta (interface)
Primeiramente vamos criar o nosso Visitor, pois ele define os objetos responsáveis pelas atualizações:
package br.com.camilolopes.visitor;
import br.com.camilolopes.classes.ContaCorrente;
import br.com.camilolopes.classes.ContaPoupanca;
/*O tal do Visitor que define os objetos responsaveis
* pelas atualizações: Conta Corrente & Conta Poupança
*/
public interface AtualizadorConta {
void atualiza(ContaCorrente contaCorrente);
void atualiza(ContaPoupanca contaPoupanca);
}
Claro que ainda não temos as classes ContaCorrente e ContaPoupanca. Portanto, vamos criá-las em alguns minutos. Mas antes precisamos criar a nossa classe abstract Conta e a interface Atualizável, que representa um Element, ou seja, sabemos os objetos que podem ser atualizados pelo Visitor.
Atualizavel.java (interface)
package br.com.camilolopes.interfaces;
import br.com.camilolopes.visitor.AtualizadorConta;
/*Element: interface que define os objetos que podem
* ser atualizados por um Visitor
*
*/
public interface Atualizavel {
void atualiza(AtualizadorConta atualizadorConta);
}
Conta.java
A classe Conta implementa a Interface Atualizável. Isso, lá na frente, vai evitar o uso de if/else encadeados para verificar o tipo. Você vai ver que não temos if/else no nosso código, tudo é baseado no tipo do objeto. Muito show!!!
package br.com.camilolopes.classes;
import br.com.camilolopes.interfaces.Atualizavel;
publicabstractclass Conta implements Atualizavel {
privatedouble saldo;
public Conta(double saldo) {
this.saldo = saldo;
}
publicdouble getSaldo() {
return saldo;
}
publicvoid setSaldo(double saldo) {
this.saldo = saldo;
}
}
ContaCorrente.java
package br.com.camilolopes.classes;
import br.com.camilolopes.visitor.AtualizadorConta;
public class ContaCorrente extends Conta{
private double saldo;
public ContaCorrente(double saldo) {
super(saldo);
this.saldo = saldo;
}
public void setSaldo(double saldo) {
this.saldo = saldo;
}
public double getSaldo() {
return saldo;
}
@Override
public void atualiza(AtualizadorConta atualizadorConta) {
atualizadorConta.atualiza(this);
}
}
ContaPoupanca.java
package br.com.camilolopes.classes;
import br.com.camilolopes.visitor.AtualizadorConta;
public class ContaPoupanca extends Conta{
private double saldo;
public ContaPoupanca(double saldo) {
super(saldo);
this.saldo = saldo;
}
public void setSaldo(double saldo) {
this.saldo = saldo;
}
public double getSaldo() {
return saldo;
}
@Override
public void atualiza(AtualizadorConta atualizadorConta) {
atualizadorConta.atualiza(this);
}
}
Agora precisamos criar a classe que tem as contas, ou seja, um Banco tem N tipos de contas. Então criamos a nossa classe Banco responsável por ter as contas.
Banco.java
package br.com.camilolopes.classes;
import java.util.ArrayList;
import java.util.List;
import br.com.camilolopes.visitor.AtualizadorConta;
public class Banco {
private List<Conta> contas = new ArrayList<Conta>();
public List<Conta> getContas() {
return contas;
}
public void setContas(List<Conta> contas) {
this.contas = contas;
}
public void atualizando(AtualizadorConta atualizadorConta){
for (Conta conta :this.contas) {
/*aqui que tem a mágica
* chama a conta com base no tipo
* evitamos if/else encadeados
*/
conta.atualiza(atualizadorConta);
}
}
}
note: Observe que nossa lista é focada na classe abstract. Se amanhã surgir um novo tipo de conta, precisamos apenas informar ao Visitor o novo tipo de conta e o que ele precisa atualizar.
Pronto! Tudo já certinho. Vamos testar para ver se de fato as atualizações na coleção acontecem com base no tipo do objeto. Para isso criei uma classe com o método main:
VisitorMain.java
package br.com.camilolopes.main;
import java.util.ArrayList;
import java.util.List;
import br.com.camilolopes.classes.AtualizaConta;
import br.com.camilolopes.classes.Banco;
import br.com.camilolopes.classes.Conta;
import br.com.camilolopes.classes.ContaCorrente;
import br.com.camilolopes.classes.ContaPoupanca;
public class VisitorMain {
public static void main(String[] args) {
//lembre-se um banco tem N contas
List<Banco> lista = new ArrayList<Banco>();
//criando as contas
ContaCorrente contaCorrente = new ContaCorrente(100.00);
ContaPoupanca contaPoupanca = new ContaPoupanca(1000.00);
//criando o Banco
Banco bancoX = new Banco();
//adicionando as contas ao Banco
bancoX.getContas().add(contaPoupanca);
bancoX.getContas().add(contaCorrente);
lista.add(bancoX);
AtualizaConta atualizaConta = new AtualizaConta();
//atualizando as contas por Banco
for(Banco banco : lista){
banco.atualizando(atualizaConta);
}
//verificando atualização
for(Banco b :lista){
for(Conta c : b.getContas()){
System.out.println(c.getClass().getSimpleName() + ” ” + c.getSaldo());
}
}
}
}
Resultado
A seguir temos o resultado. Veja que os valores foram atualizados com base no cálculo:
GitHub
Os projetos Java da série estão no meu GitHub: https://github.com/camilolopes/workspacedesignpattern.git
Feito pessoal. Vou ficando por aqui… espero que vocês tenham gostado do post e da série DesignPattern.
Abracos, see ya!!