Criando GenericDAO e DAOFactory em poucos passos

Ola pessoal,

No post de hoje vamos ver como criar genericDAO e DAOFactory  em poucos passos. O objetivo maior aqui é colocar a mão na massa. Os conceitos DAO Design Pattern não serão abordados, pois o que não falta é explicação na internet sobre o assunto. Vou considerar que você sabe conceitualmente um DAO, mas que nunca implementou  de forma genérica.

Lets go…

 

Primeiro passo

Cria a interface GenericDAO :

public interface GenericDAO<T,Type extends Serializable> {

void beginTransaction();

void commitTransaction();

void save(T entity);

void delete (T entity);

List<T> listAll();

}

O código acima usa apenas o recurso de generics do Java 5, deixando a interface que extends dizer qual será o tipo para T e o para Type.

O que significa cada um?

Simples: o T será a classe, ou seja, a entidade. O Type representará o tipo que usaremos para o Id da entidade. Você pode estar se perguntando pq a letra T e a palavra type. Apenas segui uma convenção, mas poderia ser qualquer outra letra ou nome.

Agora precisamos criar a interface dos nossos DAO, que nesse caso teremos as seguintes interfaces: ClientDAO e AccountDAO.

public interface AccountDAO extends GenericDAO<Account, Long>{

}

public interface ClientDAO extends GenericDAO<Client, Long> {

}

Observe que nas nossas interfaces é que definimos para qual entidade ela está associada e qual será o tipo do nosso ID.

É nessa interface que colocamos os métodos específicos para o nosso DAO.

Abstract HibernateDAO

Criaremos uma classe abstract que vai implementar o métodos abstract da interface GenericDAO. E nossas classes concentras vão extends a HibernateDAO como veremos a seguir. Mas antes disso precisamos criar uma classe utilitária que chamei de HibernateUtil, que terá o método para obtermos a sessão, iniciar a transação, commit, etc.

public class HibernateUtil {

private static SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

private static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

public static Session getSession() {

Session session = threadLocal.get();

if (session == null) {

session = sessionFactory.openSession();

threadLocal.set(session);

}

return session;

}

public static void beginTransaction() {

getSession().beginTransaction();

}

 public static void commitTransaction() {

getSession().getTransaction().commit();

public static void rollBackTransaction() {

getSession().getTransaction().rollback();

}

public static void closeSession() {

getSession().close();

}

}

E na classe HibernateDao temos o código a seguir:

public abstract class HibernateDAO<T, Type extends Serializable> implements GenericDAO<T, Type>{

private Class<T> persistentClass;

public HibernateDAO(Class persistentClass) {

super();

this.persistentClass = persistentClass;

}

@Override

public void beginTransaction() {

HibernateUtil.beginTransaction();

}

@Override

public void commitTransaction() {

HibernateUtil.commitTransaction();

}

@Override

public void save(T entity) {

HibernateUtil.getSession().saveOrUpdate(entity);

}

@Override

public void delete(T entity) {

HibernateUtil.getSession().delete(entity);

}

@Override

public List<T> listAll() {

HibernateUtil.beginTransaction();

Criteria criteria = HibernateUtil.getSession().createCriteria(persistentClass);

return criteria.list();

}

}

Observe que implementamos todos os métodos da GenericDAO, assim a classe que extends já tem a implementation done, ou seja, aquilo que é comum para qualquer  classe DAO já vai estar implementado e disponível na classe pai.

Concrete DAO

Agora vamos criar a classe concreta que terá a implementação específica para cada DAO.

class HibernateClientDAO extends HibernateDAO<Client, Long> implements  ClientDAO {

public HibernateClientDAO(){

//                           we passing the entity for super class

super(Client.class);

}

}

Como não temos nada de específico para implementar da interface ClientDAO deixaremos o código assim. Observe que no construtor passei qual será o tipo T, que nesse caso será a class do Client.

DAOFactory

Agora vamos criar um DAOFactory que será responsável por criar as instâncias das classes Hibernate. A classe DAOFactory será abstract e tendo apenas um método implementado que será o getFactory, o qual terá como objetivo simplesmente de retornar uma instância da classe.

public abstract class DAOFactory {

private static final Class FACTORY_CLASS = HibernateDAOFactory.class;

public static DAOFactory getFactory(){

try {

return (DAOFactory) FACTORY_CLASS.newInstance();

} catch (InstantiationException e) {

// TODO Auto-generated catch block

throw new RuntimeException();

} catch (IllegalAccessException e) {

// TODO Auto-generated catch block

throw new RuntimeException();

}

}

public abstract ClientDAO getClientDAO();

public abstract AccountDAO getAccountDAO();

}

Em seguida adicionamos os métodos que retornam a instância para as classes que implementam as interfaces ClientDAO e AccountDAO.

Agora teremos uma classe que implementa os métodos do DAOFactory, que será a classe HibernateDAOFactory.

public class HibernateDAOFactory  extends DAOFactory{

@Override

public ClientDAO getClientDAO() {

return new HibernateClientDAO();

}

@Override

public AccountDAO getAccountDAO() {

return new HibernateAccountDAO();

}

}

Observe que apenas instanciamos as classes para cada DAO. Agora vamos criar  HibernateAccountDAO

class HibernateAccountDAO extends HibernateDAO<Account, Long> implements AccountDAO {

public HibernateAccountDAO() {

super(Account.class);

}

}

E para testar, criaremos uma classe com o método main:

public class MainBank {

public static void main(String[] args) {

//                           getting instance of the factory

DAOFactory daoFactory = DAOFactory.getFactory();

//                           getting intance of clientDAO and starting transaction

daoFactory.getClientDAO().beginTransaction();

ClientDAO clientDAO = daoFactory.getClientDAO();

Client client = new Client();

client.setName(“Camilo Lopes”);

//                           creating object of the entity

Account checkigAccount = new Account();

checkigAccount.setAccountType(AccountType.CHECKING_ACCOUNT);

//                           associate acocunt with the client

checkigAccount.setClient(client);

//                           money available in account

checkigAccount.setBalance(BigDecimal.ONE);

client.getAccount().add(checkigAccount);

//                           saveing in hibernate session

clientDAO.save(client);

AccountDAO accountDAO = daoFactory.getAccountDAO();

accountDAO.save(checkigAccount);

//                           commit

clientDAO.commitTransaction();

}

}

Resultado

É isso ai pessoal, espero que tenham gostado. Vou ficando por aqui. 

See ya!!!

Série DesignPattern:Builder

Olá Pessoal,

No post da série de hoje vamos conhecer mais um Design Pattern: o Builder. Ele pertence aos Padrões de criação. No post vamos entender melhor o objetivo desse padrão e teremos um exemplo prático para desenvolver e entender à nível de código Java como as coisas acontecem, ou seja, será uma pequena prova de conceito.  Como sempre buscarei usar uma linguagem informal e direta.

Lets go…

Builder

É uma interface que define os passos para criação do produto.

Exemplo:

“para gerar um boleto informe:  sacado,cedente, valor, vencimento, NossoNro e após que você informar tudo isso terá um boleto pronto (ou seja, retorne um boleto pronto)”

Permitir separar a construção do objeto e sua representação, possibilitando a construção passo-passo do objeto, esse é o objetivo do Builder.

Exemplo: Boleto Bancário

Cada banco possui informações específicas no boleto, mas todos devem seguir (implementar) as regras básicas FEBRABAN.

O padrão Builder é formado por:

  • Product (boleto): a interface que define os objetos a serem construídos pelo Builder. Podemos usar um exemplo tentando responder a seguinte pergunta: o que um boleto precisa?
    Resposta: sacado, cedente, código de barras, valor e vencimento. (claro que há outras informações requeridas, mas me limitei a essas).
  • Builder: é uma interface que define os passos para criação do produto.
  • ConcreteBuilder: cria o Product (boleto).
  • Director: chama o builder (qualquer implementação de Builder) para construir o produto. “Ei, passe as informações que teremos no boleto para o JoãoBuilder que ele vai gerar um para você.”

Praticando…
Nada melhor que praticar não é? Então a seguir vamos ver como ter o padrão Builder em uma aplicação Java.

Criaremos um projeto conforme a imagem a seguir:

Passo 1
O primeiro passo é pensar como você pode gerar N boletos de maneira simples e de fácil manutenção. Há N bancos no mercado: Itaú, Bradesco, Banco do Brasil etc, e cada dia novos bancos vão surgindo e talvez sua aplicação terá que dar suporte àquele novo banco que, quando você desenvolveu a aplicação, não existia. Mas você quer fazer isso da forma mais simples possível. Adicionar um novo banco emissor de boletos não pode ser algo custoso para seu projeto.
Então vamos ter:

  • – uma interface chamada Boleto: interface tem como objetivo de dizer a cada banco o que um boleto tem e deve ser preenchido. Por exemplo:
    Um boleto deve ter: quem é o sacado, cedente, uma data de vencimento e um valor”. Independente do banco ou produto, um boleto tem quer ter essas informações preenchidas, do contrário não temos um boleto pronto para uso.

package com.camilolopes.interfaces;

import java.util.Calendar;
/*
* interface que define o que um boleto
* deve ter. qualquer banco quer tem interesse em gerar
* um boleto deve informar quem é o sacado, cedente
* o prazo para pagto e o valor.
*/
public interface Boleto {
String getSacado();
String getCedente();
Calendar getVencimento();
double getValor();

}

Passo 2
Uma vez que já definimos o que deve constar em um boleto para que ele possa ser gerado, agora vamos criar uma interface quer será capaz de criar o boleto. É essa interface que vai dizer aos bancos o que eles devem informar para ter o boleto, ou seja, é o nosso Builder:

package com.camilolopes.interfaces;

import java.util.Calendar;

/*
* interface para criação do Product
*/
public interface BoletoBuilder {
void buildSacado(String sacado);
void buildCedente(String cedente);
void buildValor(double valor);
void buildVencimento(Calendar vencimento);
void buildNossoNro(int nossoNro);

Boleto getBoleto();
}

Observe que agora definimos que na geração do boleto um número de controle é passado. Mas por que isso não está no Boleto? Simples, porque nesse caso não é obrigatório que o banco tenha um número de controle interno para gerar um boleto. Ele pode gerar N boletos para diferentes clientes e manter o número de controle (nossoNro) com o mesmo valor. Isso não impacta na regra de negócio de um boleto.

Passo 3
Uma vez que já definimos o que o boleto deve ter e como ele deve ser construído, agora vamos criar as classes (os bancos) que terão interesse em gerar um boleto.

ItauBoleto.java

package com.camilolopes.classes.impl;

import java.util.Calendar;

import com.camilolopes.interfaces.Boleto;
/*
* cada instituicao financeira monta o seu boleto
*/

public class ItauBoleto implements Boleto {

private String sacado;
private int nossoNro;
private Calendar vencimento;
private double valor;
private String cedente;

public ItauBoleto(String sacado, String cedente, double valor,
Calendar vencimento, int nossoNro) {
this.sacado =sacado;
this.cedente = cedente;
this.valor = valor;
this.vencimento = vencimento;
this.nossoNro = nossoNro;
}

@Override
public String getSacado() {
// TODO Auto-generated method stub
return sacado;
}

@Override
public String getCedente() {
// TODO Auto-generated method stub
return cedente;
}

@Override
public Calendar getVencimento() {
// TODO Auto-generated method stub
return vencimento;
}

@Override
public double getValor() {
// TODO Auto-generated method stub
return valor;
}

@Override
public String toString() {
return “ItauBoleto [sacado=” + sacado + “, nossoNro=” + nossoNro
+ “, vencimento=” + vencimento.getTime() + “, valor=” + valor
+ “, cedente=” + cedente + “]”;
}

}

Essa classe apenas implementa o Boleto informando e seus respectivos métodos. O método toString() é o mais importante, pois retornamos os dados do boleto quando obtemos o objeto dessa classe. Se eu quiser adicionar um logomarca ou informação extra no boleto é nesse momento que vamos implementar.

Note: infelizmente a data não está formatada comercialmente, mas não é o objetivo do post.

Passo 4
Agora eu já tenho o meu boleto para o Itaú, que é o ItauBoleto. Porém ele não é gerado ainda, preciso ter alguém que gere esse boleto. Ao consultar o sr. Builder ele falou que não pode fazer nada, apenas dizer o que eu preciso para gerar um boleto. Segundo sr. Builder, para gerar um boleto eu preciso dizer:o sacado, o cedente, valor, vencimento e um nro de controle.

ItauBoletoBuilder.java

package com.camilolopes.classes.impl;
import java.util.Calendar;
import com.camilolopes.interfaces.Boleto;
import com.camilolopes.interfaces.BoletoBuilder;

/*
* a instituicao tem um criador de boletos
*/
public class ItauBoletoBuilder implements BoletoBuilder {

private String sacado;
private String cedente;
private double valor;
private Calendar vencimento;
private int nossoNro;

@Override
public void buildSacado(String sacado) {
this.sacado = sacado;

}

@Override
public void buildCedente(String cedente) {
this.cedente = cedente;

}
@Override
public void buildValor(double valor) {
this.valor = valor;

}
@Override
public void buildVencimento(Calendar vencimento) {
this.vencimento = vencimento;

}
@Override
public void buildNossoNro(int nossoNro) {
this.nossoNro = nossoNro;
}
@Override
public Boleto getBoleto() {

return new ItauBoleto(sacado,cedente,valor,vencimento,nossoNro);
}
}

Agora sim já podemos obter um objeto Boleto pronto para uso. Uma vez que o ItauBoletoBuilder já pode construir um Boleto com base nas informações que ele recebe.

Passo 5
Porém a classe anterior apenas constrói um boleto para o ItauBoleto e o usuário não quer conhecer a construção de boleto, ele apenas quer passar um objeto de um dos bancos disponíveis  para que o boleto seja gerado. Para isso precisamos criar um GerenciadorDeBoletos que é capaz de gerar um boleto com base no tipo do objeto.

package com.camilolopes.generator;

import java.util.Calendar;

import com.camilolopes.interfaces.Boleto;
import com.camilolopes.interfaces.BoletoBuilder;
/*
* classe que gera o boleto a partir do xxBuilder
*/
public class GeneratorBoleto {
//código orientado a interfaces
private BoletoBuilder boletoBuilder;
//espero um objeto que implemente o criador de boleto
public GeneratorBoleto(BoletoBuilder boletoBuilder) {
super();
this.boletoBuilder = boletoBuilder;
}

public Boleto geraBoleto(){
//informações sobre o boleto a ser gerado
boletoBuilder.buildSacado(“Camilo Lopes”);
boletoBuilder.buildCedente(“Disney”);
boletoBuilder.buildValor(2000.00);

Calendar vencimento = Calendar.getInstance();
vencimento.add(Calendar.DATE, 20);
boletoBuilder.buildVencimento(vencimento);
boletoBuilder.buildNossoNro(1234);
//olha isso aqui que mágico
Boleto boleto = boletoBuilder.getBoleto();
return boleto;
}
}

E assim obtemos o objeto Boleto pronto para uso. Na classe Gerador de boletos não há nenhuma particularidade  de qual banco será gerado o boleto. Tudo isso depende do tipo do boleto recebido, ou seja, o que foi escolhido para ser gerado.

Passo 6
Podemos criar uma classe com o método main para visualizar o resultado. Vamos ver:

package com.camilolopes.main;

import com.camilolopes.classes.impl.ItauBoletoBuilder;
import com.camilolopes.generator.GeneratorBoleto;
import com.camilolopes.interfaces.Boleto;
import com.camilolopes.interfaces.BoletoBuilder;

public class GeradorBoletoMain {
public static void main(String[] args) {
BoletoBuilder boletoBuilder = new ItauBoletoBuilder();
GeneratorBoleto generatorBoleto = new GeneratorBoleto(boletoBuilder); //itau
Boleto boleto = generatorBoleto.geraBoleto();//retorna o boleto pronto
System.out.println(boleto);
}

}

O resultado será:

Resumindo…
Para finalizar, observe que com o padrão Builder definimos uma forma que os boletos podem ser gerados, ou seja, temos que implementar a interface Builder, é a única forma de construir um Boleto e para gerar temos uma classe responsável por qualquer tipo de Boleto, ou seja, ele gera boleto para qualquer classe que tem o boleto já construído, que nesse caso deve implementar BoletoBuilder (o nosso Builder). Adição de um novo banco é muito simples, o novo banco apenas precisa implementar a interface, nada no gerador é alterado. Observe o quanto isso é eficiente. Talvez se você não conhecesse o padrão Builder pensou em implementar usando if/else. Hmmm isso seria um inferno na sua vida, pois ia crescer/diminuir de acordo com a necessidade de negócio de ter mais ou menos bancos, sem falar que a legibilidade do código estaria comprometida.

Git Hub 

Os projetos encontram-se no Github:

https://camilolopes@github.com/camilolopes/workspacedesignpattern.git 

Vou ficando por aqui e espero que tenham gostado de mais um post da série DesignPattern não é receita de bolo.

Abraços, see ya!

Série DesignPattern: Factory Method

Olá Pessoal,

Dando continuidade a série “Design Pattern não é receita de bolo” hoje vamos conhecer o padrão Factory Method que pertence aos Padrões de Criação. Para quem não acompanhou o ultimo post, conhecemos como Design Pattern é dividido, saber qual padrão usar é tão importante quanto saber que tipo de padrão ele pertence.

Lets go…

Download do Projeto

Os projetos que serão usados no post estão no meu GitHub:

https://github.com/camilolopes/workspacedesignpattern

note: Sei que para alguns nem merecia colocar esse note por ser obvio, mas por medida de segurança achei bom não faltar. Esqueça tradução ao querer estudar Design Pattern. É em inglês o nome do padrão e evite ao máximo de traduzir. O motivo, que a tradução atrapalha mais do que ajuda.

Factory Method (Padrão de Criação)

Encapsula a escolha da classe concreta na criação de objetos de um TIPO.Ou seja, é quando tenho várias “respostas” com base no TIPO passado.

Exemplo:
se o cliente é JURIDICO(do tipo juridico) envio uma mensagem com o CNPJ;
se o cliente é FISICO(do tipo fisico) envio  uma mensagem com CPF;

Esse padrão normalmente tem um intermediario que ajuda decidir qual implementacao da classe concreta será chamada com base no tipo da chamada.

Esqueleto do padrão

  • Product: é interface que define o objeto a ser criado
  • ConcreteProduct: implementação particular do tipo do objeto a ser criado
  • Creator: classe/interface que define a assinatura do metodo responsavel pela criacao do produto
  • concreteCreator: classe que implementa ou sobrescreve o método de criação do produto.

Na prática

Veremos agora na pratica ele em ação, crie um projeto seu Eclipse e chame como achar melhor, aqui chamei de  FactoryMethodPessoa com essa estrutura:

Deixe seu projeto conforme a imagem acima. A seguir vamos meter mão na massa.

Desenvolvendo
Chegou a hora de desenvolver. O ponto mais importante ao querer entender como usar o design pattern X ou Y. É entender o objetivo dele. Na maioria das vezes, um design pattern sempre começa por uma interface para manter o código orientado a interfaces. Mas, isso não é regra. Vou fazer um desenvolvimento orientado a questionamento e alinhamento como tipo de design pattern. Foi assim que fiz para buscar entender e saber usar na hora “H”. Eu particularmente não tive ainda a felicidade de usar todos os design pattern em uma “solução cliente”, como prova de conceito é sempre mais simples. Mas, em regra de negócio as coisas são mais dinâmicas. Vamos largar de papo e mão na massa.

Passo 1
Eu me pergunto: o que minha aplicação pode fazer?  Enviar mensagens para diferentes tipos de pessoa.
Então é bom eu ter uma interface onde cada pessoa diz como quer ser chamada.

package br.com.camilolopes.interfaces;

/* Product */
public interface Envio {
void enviar(String mensagem);
}

Posso dizer que o serviço de envio de mensagens é um produto? Sim. E que será implementado com base no tipo de mensagem que deseja enviar.

Passo 2
Agora precisamos definir que tipo de mensagens vamos poder enviar. No nosso exemplo, podemos mandar mensagens com o CPF ou CNPJ, porém isso depende do tipo do cliente. Não posso mandar CPF para um cliente que é pessoa Juridica. A seguir temos a implementação da maneira mais simples, possível o objetivo é entender o design pattern.

PessoaFisica.java

package br.com.camilolopes.classes.impl;
import br.com.camilolopes.interfaces.Envio;
/*
* concreteProduct
*/
public class PessoaFisica implements Envio {
@Override
public void enviar(String mensagem) {
System.out.println(mensagem + “CPF “);
}}

PessoaJuridica.java

package br.com.camilolopes.classes.impl;
import br.com.camilolopes.interfaces.Envio;
/*
* ConcreteProduct
*/
public class PessoaJuridica implements Envio {
@Override
public void enviar(String mensagem) {
System.out.println(mensagem + “CNPJ”);
}}

Observe que para cada PessoaXX passamos uma mensagem  + uma informação privada que cada um tem. Que nesse caso seria o CPF e CNPJ. Pense assim à nivel de negócio:
“Se eu estou me comunicando com Pessoa Juridica as minhas negociações, contrato serão feitas em cima de um CNPJ, é ele que é importante na relação.” Então nesse contexto se eu quiser mandar uma  mensagem e no final envio o cnpj para confirmação.

Exemplo:
“Houve uma alteração de contrato para o CNPJ xxx”

Passo 3
Já temos as implementações do produto. Agora que vem a parter do Factory Method, onde precisamos chamar cada implementação com base no tipo. Algo assim:

Se for PessoaFisica
    chame new PessoaFisica().enviar
senão se for PessoaJuridica
    chame new PessoaJuridica().enviar

ifs encadeados nunca é uma boa opção, afeta a legibilidade e manutenção do código. Sem falar que amanhã pode nascer um novo tipo de PessoaXXX e teremos que aumentar mais ainda essa condição if/else. E veremos a seguir que conseguirmos evitar isso através do padrão factory method.

Criaremos uma classe que retorna o tipo do objeto com base no que foi passado para ele. E com esse retorno, chamaremos uma das implementações da nossa interface (Product). Veja:

package br.com.camilolopes.creator;
import br.com.camilolopes.interfaces.Envio;
/*
* classe que vai retornar o metodo implementado
* com base no tipo que recebeu
*/
public class CreatorEnvio {
//o segredo que evita N if/else encadeados \o/
public Envio getEnvio(Envio envio){
if (envio==null) {
throw new NullPointerException();
}
return envio;
}
}

Observe o segredo todo está aqui. Estamos com o código orientado à interfaces. O nosso método espera qualquer objeto que seja do tipo Envio, ou seja, qualquer implementação da interface. Verificamos se é null para não acontecer NullPointerException ao chamar o método e em seguida retornamos o objeto que recebemos.
E agora?
Simples. A classe principal que envia as mensagens, chamará CreatorEnvio passando para o tipo de pessoa que ele deseja enviar a mensagem e que mensagem será enviada. Veja:

package br.com.camilolopes.main;
import br.com.camilolopes.classes.impl.PessoaFisica;
import br.com.camilolopes.classes.impl.PessoaJuridica;
import br.com.camilolopes.creator.CreatorEnvio;
import br.com.camilolopes.interfaces.Envio;

public class MainPessoa {

public static void main(String[] args) {
CreatorEnvio creator = new CreatorEnvio();

//enviando mensagem para pessoa fisica
Envio envio = creator.getEnvio(new PessoaFisica());
envio.enviar(“caro cliente inscrito no “);

//enviando para pessoa juridica
envio = creator.getEnvio(new PessoaJuridica());
envio.enviar(“Prezada Empresa inscrita no “);
}
}

Observe que é muito simples, todo código orientado à interfaces. Se amanhã nascer um novo tipo de Pessoa, não precisamos nos preocupar, apenas passaremos isso para o método getEnvio e ele chamará a implementação de enviar(mensagem) daquele novo tipo de PessoaXX.

O resultado

Eu gosto de criar unit tests, a seguir tem o unit test que fiz para validar. Com unit test não precisamos ter uma classe com o método main para saber se o nosso código está funcionando. Veja:

package br.com.camilolopes.creator;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import br.com.camilolopes.classes.impl.PessoaFisica;
import br.com.camilolopes.classes.impl.PessoaJuridica;
import br.com.camilolopes.creator.CreatorEnvio;

public class CreatorEnvioTest {

private CreatorEnvio creatorEnvio;

@Before
public void setUp() throws Exception {
creatorEnvio = new CreatorEnvio();
}

@Test
public void testGetPessoaFisica() {
assertTrue(creatorEnvio.getEnvio(new PessoaFisica()) instanceof PessoaFisica);
}

@Test
public void testGetPessoaJuridica() {
assertTrue(creatorEnvio.getEnvio(new PessoaJuridica()) instanceof PessoaJuridica);
}

@Test(expected = NullPointerException.class)
public void testNullIsInvalid() {
creatorEnvio.getEnvio(null);
}
}

Criei apenas um unit test para a classe CreatorEnvio e verifiquei se ele estava retornando o tipo do  objeto correto com base no que foi passado para o método getEnvio.

Git Hub 

Os projetos encontram-se no Github:

https://camilolopes@github.com/camilolopes/workspacedesignpattern.git 

Vou ficando por aqui espero que tenham gostado do post. Apesar de ter ficado grande devido a parte pratica hehe.

Abracos, see ya

Série Design Pattern: Não é Receita de Bolo

Olá Pessoal,
Estarei dando inicio à mais uma série aqui no blog. E dessa vez será sobre Design Pattern. Claro que não abordarei todos os padrões (até porque não tenho experiência de ter usado todos no dia-dia, na minha opinião fazer um projeto como prova de conceito é uma coisa e usar para resolver problemas de cliente é outra.Não posso assumir que sei algo só porque fiz uma prova de conceito um house made e deu certo), mas aqueles que considerei importantes e que é muito comum no dia-dia. Uma vez que, para padrões não há uma receita de bolo, e sim que depende muito do contexto. E não se preocupe se você não sabe todos os design pattern de cabeça ao olhar um problema. Até por que a ideia não é decorar e sim saber usar, ter um bom livro de design pattern na sua mesa sempre é bom.
Para essa série não vou seguir um padrão em cada post, pois tudo depende do tipo do padrão que vou abordar, alguns nem precisam de código para entender, outros são tão abstratos que é preciso desenhar, enfim vou buscar usar diferentes formas de tentar explicar cada design pattern da série de forma que você ao término do post saiba o objetivo tanto teórico e uma ideia pratica de onde como usá-lo.

Lets go…

Design Pattern
Antes de mais nada é preciso conhecer os padrões: criação, estruturais e comportamentais. Pois, eles dizem qual padrão iremos usar. Por exemplo: se preciso adotar um padrão para criação de objetos, terei que olhar  para os padrões existentes  em “Padrões de criação”. Por que lá? Veremos daqui à pouco.

Então não adianta querer decorar os padrões. Na verdade eles não foram feitos para serem decorados e saber quando aplica-los de acordo com o contexto. Design Pattern não é receita de bolo, que se você seguir do passo 1 até o 10, vai ter a solução. Alias a solução do seu “problema” é com você. Design Pattern não é uma biblioteca com resoluções de problemas.

Conhecendo os Padrões

A seguir fiz uma definição de maneira mais simples e objetiva possível para cada padrão.

Note:  Quando você tiver com algum problema de design, pense em que tipo de problema que você tem antes de adotar algum padrão.

  • Padrões de criação: ajuda a encapsular  a criação de objetos de um TIPO. Ou seja, é quando temos várias “respostas” com base no tipo do objeto passado.

São eles:factory method,abstract method, builder, prototype, singleton, multiton, object pool

Exemplo:  Se o objeto é do tipo pessoa juridica eu vou fazer isso: “Olá xxx,  CNPJ:111”. Mas, se for pessoa fisica é assim: “olá xxx, CPF:0000”.

  • Padrões Estruturais: Está relacionado as interações entre os objetos no sistema. Ou seja, é como os meus objetos vão se relacionar com os outros objetos. Busca evitar o alto acomplamento entre objetos.

São eles:adapter, bridge, composite, decorator, facade, front controller, flyweight, proxy

Então quando você precisar definir como será as interações entre objetos, não esqueça em dar uma olhada nos Padrões Estruturais e ver qual deles podem atender à sua necessidade.

  • Padrões Comportamentais: está relacionado  em saber as intenções  que um objeto pode fazer e como ele se relaciona com os outros objetos.

São eles:command, iterator, mediator, observer, state, strategy, template method, visitor

Como estudar?

Há dois livros bem famosos sobre o assunto. Um deles é do Erich Gama: Design Patterns: Elements of Reusable Object-Oriented Software e o outro é da série use a cabeça: Head First Design Pattern. E qual comprar?
Eu recomendo os dois.A ordem de leitura na minha opinião seria primeiro o da série Head First, caso você seja iniciante no assunto. O livro é bem didático. O do Erich eu diria é quando já temos uma certa dose de conhecimento sobre design pattern e queremos entender com mais detalhe. Há trechos no livro que o autor não é muito claro, e que para conseguir entender o que ele quis dizer é preciso já ter uma certa base de Design Pattern do contrário a informação fica perdida.  O livro do Erich Gamma é uma especie de referência que deve ficar na sua mesa para consultar. Até pq você não vai decorar os design pattern.

Git Hub 

Os projetos da série  estão Github:

https://camilolopes@github.com/camilolopes/workspacedesignpattern.git 

Abracos, vou ficando por aqui e espero que tenham gostado desse primeiro post. No próximo já vamos brincar colocando mão na massa.
See ya!!!