Olá Pessoal,
No post de hoje vamos conhecer o padrão Bridge. Não é muito difícil surgir a necessidade do uso deste padrão. No exemplo de hoje você vai ver o motivo. Apesar de que você pode pensar: “hm, eu já implementei ele, mas nem fazia ideia”. Sim, isso é comum mesmo. Mas revise e veja se fez orientado à interfaces, pois é ai que está o pulo do gato.
Let’s go…
Bridge
A definição dele é bem curta veja:
“Separa a abstracao da representação de forma que ambos possam variar e produzir tipos de objetos diferentes”.
O que isso quer dizer?
Vamos ver de forma prática e com um exemplo do dia-dia. É comum em uma aplicação precisar gerar arquivos em formatos diferentes, certo? Se você desenvolve apenas focado nos formatos suportados atualmente terá um problema futuramente, caso surja a necessidade de suportar novos formatos. Vamos dizer que hoje sua aplicação gere arquivos apenas no formato .txt e .pdf., mas amanhã é necessário gerar arquivos no formato .doc e .xls. A forma que você implementa essa geração de arquivos vai dizer se isso custará muito ou não para o seu projeto. É preciso separar a abstração da representação (arquivo) com as formas que ele pode ser produzido. Independente do formato escolhido ele não deixa de ser um arquivo, o que varia ou muda é o tipo do arquivo. Captou a definição do Bridge?
Desenvolvimento
Vamos agora colocar mão na massa para ficar mais divertido e entender de fato o padrão Bridge. No projeto de hoje vamos poder gerar arquivos em diversos formatos. Nada de especial ai, porém tudo começa a ficar interessante se amanhã minha aplicação precisar suportar um formato especifico e ai que terei o “pulo do gato” ou não.
Passo 1
Crie um projeto conforme o meu a seguir:
Passo 2
Vamos pensar nos perguntando, certo?
O que eu quero?
R: Poder gerar um arquivo
Para quais formatos?
R: Os disponíveis na aplicação
Para a primeira pergunta vamos criar uma interface. O motivo é que nem tudo no sistema gera um arquivo, apenas em classes especificas de negócios fazem sentido gerar arquivos, como por exemplo:
Gerar um recibo para o cliente (classe recibo);
Gerar um arquivo com as despesas (classe despesas)
etc
Então as classes que precisam gerar um arquivo tem que implementar a interface, informar os dados que serão gerados e o tipo de arquivo desejado.
package br.com.camilolopes.bridge.interfaces;
/*
* sempre que precisar gerar um arquivo
* temos que implementar essa interface
* e dizer o que teremos nesse arquivo
*/
public interface Arquivo {
void geraArquivo();
}
Passo 2
Antes de definirmos quais classes da nossa aplicação são capazes de gerar arquivos, vamos criar o nosso gerador de arquivos, que na verdade será o Bridge na aplicação. Ele não passa de uma interface que será implementada pelos formatos suportados.
package br.com.camilolopes.bridge.interfaces;
/*
* essa interface serão implementadas pelo
* tipos de arquivos suportados a serem gerados
* txt,pdf,zip,doc etc
*/
public interface GeradorDeArquivo {
void criarArquivo(String dados);
}
Passo 3
Agora vamos dizer quais os formatos suportados. Aqui está o “pulo do gato”, se precisar adicionar um novo formato é só criar uma classe para o formato desejado e implementar a interface GeradorDeArquivo. Essa é a regra. E assim, todas as classes (recibo, desespas etc) podem gerar arquivos no novo formato disponível.
package br.com.camilolopes.bridge.classes;
import java.io.FileNotFoundException;
import java.io.PrintStream;import br.com.camilolopes.bridge.interfaces.GeradorDeArquivo;
/*
* classe que gera arquivo txt
*/
public class GeradorArquivoTxt implements GeradorDeArquivo {@Override
public void criarArquivo(String dados) {
try{
PrintStream arquivo = new PrintStream(“arquivo.txt”);
arquivo.println(dados);
arquivo.close();
System.out.println(“Arquivo gerado com sucesso”);
}catch (FileNotFoundException e) {
e.printStackTrace();
}}
}
Passo 4
Agora a classe que pode gerar arquivo (Recibo, Despesas etc). Nela delegamos a criação do arquivo para o Bridge e ele se encarrega de gerar o arquivo com o tipo que passamos.
package br.com.camilolopes.classes;
import br.com.camilolopes.bridge.interfaces.Arquivo;
import br.com.camilolopes.bridge.interfaces.GeradorDeArquivo;
/*
* classe que tem os dados que serão
* gerados os arquivos
* ela delega a geração do arquivo para um especialista no assunto
*/
public class Recibo implements Arquivo {
private String emissor;
private String favorecido;
private double valor;
/*como sempre orientado a interfaces
* assim deixamos a chamada com base no tipo
* passado
*/
private GeradorDeArquivo geradorDeArquivo;//para gerar o recibo o usuario é obrigado informar o tipo desejado
public Recibo(String emissor, String favorecido, double valor,GeradorDeArquivo tipoDoArquivo) {
super();
this.emissor = emissor;
this.favorecido = favorecido;
this.valor = valor;
geradorDeArquivo = tipoDoArquivo;
}@Override
public void geraArquivo() {
StringBuilder dados = new StringBuilder();
dados.append(“Recibo: “);
dados.append(“\n”);
dados.append(“Empresa: ” + this.emissor);
dados.append(“\n”);
dados.append(“Cliente: ” + this.favorecido);
dados.append(“\n”);
dados.append(“Valor: “+ this.valor);
//informando os dados que serão gerados
this.geradorDeArquivo.criarArquivo(dados.toString());
}
}
Observe que é obrigado ao usuário quando for gerar um arquivo, além das informações, é preciso dizer o tipo do arquivo que ele deseja.
Passo 5
Vamos testar a nossa aplicação. Criamos uma classe com o método main que informa os dados a serem gerados e o tipo de arquivo desejado e em seguida veremos se o arquivo foi gerado e se a informação foi gravada de fato.
package br.com.camilolopes.main;
import br.com.camilolopes.bridge.classes.GeradorArquivoTxt;
import br.com.camilolopes.classes.Recibo;public class TesteRecibo {
public static void main(String[] args) {
GeradorArquivoTxt arquivoTxt = new GeradorArquivoTxt();
Recibo reciboAbril = new Recibo(“XX”, “Camilo Lopes”, 50.00, arquivoTxt);
reciboAbril.geraArquivo();
}
}
Conclusão
Observe que seu código ficou muito melhor estruturado e com fácil manutenção.
Git Hub
Os projetos encontram-se no Github:
https://camilolopes@github.com/camilolopes/workspacedesignpattern.git
Vou ficando por aqui e espero que tenham gostado do post de hoje.
Abraços, see ya!!
O exemplo ficou carregado e meio perdido… 20 linhas de código explica esse padrão por completo