Clube Java http://www.clubejava.com.br Visitantes em missão de negócios Leandro Silva Nesse pequeno tutorial estudaremos um caso de utilização do design pattern Visitor na implementação de componentes de regras de negócio “plugáveis”. O padrão para visitantes Visitor é um padrão de projeto catalogado pelos “quatro” mosqueteiros da engenharia de software, Gamma, Helm, Johnson e Vlissides (Gang of Four - GoF), como um padrão de projeto comportamental. Seu objetivo principal é permitir que sejam adicionadas novas funcionalidades a classes existentes, de maneira plugável, sem que haja a necessidade de se alterar a hierarquia dessas classes. Essa é uma técnica poderosa quando se deseja construir fragmentos de regras de negócio (componentes especialistas em um dado negócio) que podem ser aplicadas sempre que for conveniente a uma classe. Padrões de Projeto Para mais informações sobre “design pattern”, leia o artigo publicado por Daniel Destro em www.guj.com.br/user.article.get.chain?article.id=137&page=1. O diagrama de classes abaixo ilustra a estrutura de Visitor: Acompanhe também a seguir o diagrama de seqüência de Visitor: Grupo de Usuários Java – http://www.guj.com.br – Página 1 Clube Java http://www.clubejava.com.br Bom, agora que já conhecemos um pouco sobre o conceito de Visitor, proponho que construamos um pequeno aplicativo para ilustrar a sua utilização na implementação de componentes de regras de negócio “plugáveis”. Quatro Cantos, dois problemas A Quatro Cantos é uma empresa que comercializa produtos artesanais e naturais muito bonitos, vindos de quatro cantos distintos do nosso país: Rio Grande do Sul, São Paulo, Bahia e Amazonas – daí a origem do nome. Hoje, ela comercializa seus produtos através da sua loja localizada na Avenida Paulo Faccini, nº 12, Guarulhos/SP, da sua Central Telefônica de Vendas (0800-777-1212) e pretendem, em um futuro bem próximo, fazer negócios também através de seu site na web (www.quatrocantos.com.br). Como citado anteriormente, a Quatro Cantos trabalha exclusivamente com produtos desses quatro estados do Brasil, e isso gera um custo de transporte (Custo de Procedência) que deve ser levado em conta na hora de calcular o preço de venda dos produtos. Além disso, todos os artesãos são verdadeiros artistas; pessoas realmente muito talentosas, por isso, a Quatro Cantos oferece a eles um contrato de fidelidade proporcionando uma porcentagem adicional sobre o valor de custo de cada produto – essa porcentagem adicional é determinada pelo estado de residência do artesão, e também é agregada ao custo de procedência do produto. Essa é a Quatro Cantos! E esses são os problemas que temos que resolver: 1) Implementar as regras de negócio que fazem o “Calculo do Custo de Procedência” de um produto, de uma maneira que, se amanhã ou depois a empresa decidir mudar seu nome para Sete Cantos e passar a comercializar produtos de mais outros três estados do país, novas regras de negócio possam ser implementadas para cobrir esses novos estados sem que as já existentes sejam comprometidas. 2) Implementar as regras de negócio que fazem o “Calculo do Valor de Venda” de um produto, de maneira diferenciada para cada veículo de venda, tendo em mente que, brevemente, eles também estarão comercializando seus produtos através de seu site na web. Visitantes especialistas solucionam problemas O diagrama de classes a seguir ilustra nossa estratégia de implementação Visitor para solucionar os problemas descritos no tópico anterior: Grupo de Usuários Java – http://www.guj.com.br – Página 2 do padrão de projeto Clube Java http://www.clubejava.com.br Creio que abstração é algo fundamental para a boa padronização. Pensando dessa maneira, padronizaremos nossa estratégia de implementação de Visitor criando duas interfaces base: Visitor e Visitable. Listagem 1 – O código de nossa interface visitante: package leandro.artigos.designpatterns.visitor; /** * @author Leandro Silva * * @jug www.clubejava.com.br */ public interface Visitor { /** * visit * * @param visitableObject O objeto que será visitado * @return Object O resultado da visita * @exception BusinessVisitException Exceções de negócio */ public Object visit(Visitable visitableObject) throws BusinessVisitException; } Abstração do Visitante A estratégia de implementação de Visitor apresentada pela GoF (Diagrama 1), trabalha com a interface do visitante um pouco menos genérica e mais focada no negócio. Em minha opinião, abstrair a interface Visitor um nível a cima, como estamos fazendo nesse aplicativo de exemplo, é uma maneira bastante interessante de se padronizar visitantes. De outra forma, para cada nova classe que quiséssemos que nosso componente de negócios (visitante) visitasse, teríamos que descrever um novo método em sua interface e implementá-lo. Mas não se preocupe com isso por enquanto, trataremos desse assunto mais adiante. Listagem 2 – O código interface para visitáveis: package leandro.artigos.designpatterns.visitor; /** * @author Leandro Silva * * @jug www.clubejava.com.br */ public interface Visitable { /** * accept * * @param visitorObject Um objeto visitante * @return Object O resultado da visita recebida * @exception BusinessVisitException Exceções de negócio */ public Object accept(Visitor visitorObject) throws BusinessVisitException; } Se visitantes especialistas resolvem problemas, eu aceito! Vimos nas listagens 1 e 2 as interfaces que definem visitantes e visitáveis, e como o quadro Abstração do Visitante comenta, optamos por uma interface visitante bastante genérica, o que além de padronizar a implementação de visitantes, também simplifica a implementação de visitáveis. Listagem 3 – O método que permite nosso Produto ser visitado: /** * accept * Grupo de Usuários Java – http://www.guj.com.br – Página 3 Clube Java http://www.clubejava.com.br * @see Visitable#accept(leandro.artigos.designpatterns.visitor.Visitor) */ public Object accept(Visitor visitorObject) throws BusinessVisitException { return visitorObject.visit(this); } A Listagem 3 ilustra a simplicidade em se implementar uma classe visitável. Não é necessário nada mais que isso para que uma classe possa ser visitada. Com essa implementação extremamente genérica de Visitable, o Produto não precisa se preocupar com detalhes a respeito do visitante. A pergunta “qual é a assinatura do método que realizará a visita”, jamais estará em pauta. Toda responsabilidade de saber como tratar cada Produto fica a cargo dos visitantes (que são nada mais, nada menos, que especialistas de negócio). Certamente esse é o tipo de herança que um pai gostaria de deixar a seus filhos, não é? E de fato é o que acontece aqui. ProdutoArtesanal e ProdutoNatural trabalham nos moldes do contrato firmado por seu pai. O lema da família produto é: “Especialistas tratam de coisas das quais são especialistas e nós não precisamos saber nada sobre isso”. Visitantes especialistas de negócio Dentro dessa filosofia de relacionamento entre visitantes e visitáveis, o visitante CalculaCustoProcedencia é realmente um especialista no que se propõe a fazer: “calcular o custo de procedência de um produto”. Não importa o tipo do produto, seja artesanal ou natural, ele sabe muito bem como tratá-lo sem dividir suas responsabilidades com esse produto. Para que isso seja possível, CalculaCustoProcedencia implementa a estratégia executor de visitas. Listagem 4 – O código que CalculaCustoProcedencia implementa para o método visit: /** * visit * * @see Visitor#visit(leandro.artigos.designpatterns.visitor.Visitable) */ public Object visit(Visitable visitableObject) throws BusinessVisitException { // Executa o "executor de visitas" apropriado return VisitorHelper.doVisit(this, visitableObject); } Certamente você deve estar se perguntando “o que é a estratégia tal executor de visitas” e “quem é essa VisitorHelper”, estou certo? Executor de visitas é a estratégia que adotaremos para auxiliar na abstração da interface de visitantes (Listagem 1. Veja também o quadro Abstração do Visitante). Com a estratégia executor de visitas podemos ter uma interface Visitor padrão, altamente genérica para todos os nosso visitantes, e apenas implementarmos as regras que são diferenciadas para cada classe visitável, na classe visitante, em um método polimórfico chamado doVisit. O visitante CalculaCustoProcedencia exemplifica bem esse conceito, conforme veremos nas listagens 5 e 6. Listagem 5 – O artesanais: executor de visitas que CalculaCustoProcedencia implementa para visitar produtos /** * doVisit * * @param produtoArtezanal ProdutoArtesanal * @return Double * @throws BusinessVisitException */ private Double doVisit(ProdutoArtesanal produtoArtesanal) throws BusinessVisitException { double percentualAdicionalProcedencia = 0; double percentualAdicionalArtesao = 0; // Esse monte de if's são apenas para ilustração de uma regra de negócio. // NA VIDA REAL esses dados poderiam vir de uma fonte de dados qualquer. if (produtoArtesanal.getProcedencia().equals(Procedencia.AM)) { Grupo de Usuários Java – http://www.guj.com.br – Página 4 Clube Java http://www.clubejava.com.br percentualAdicionalProcedencia = 20; percentualAdicionalArtesao = 1.5; } else if (produtoArtesanal.getProcedencia().equals(Procedencia.BA)) { percentualAdicionalProcedencia = 15; percentualAdicionalArtesao = 0.95; } else if (produtoArtesanal.getProcedencia().equals(Procedencia.RS)) { percentualAdicionalProcedencia = 10; percentualAdicionalArtesao = 0.5; } else if (produtoArtesanal.getProcedencia().equals(Procedencia.SP)) { percentualAdicionalProcedencia = 0; percentualAdicionalArtesao = 0.5; } double valorAdicionalProcedencia = ((produtoArtesanal.getValorCusto() / 100) * percentualAdicionalProcedencia); double valorAdicionalArtesao = ((produtoArtesanal.getValorCusto() / 100) * percentualAdicionalArtesao); double valorCustoProcedencia = valorAdicionalProcedencia + valorAdicionalArtesao; return new Double(valorCustoProcedencia); } Só o visitante enxerga seus executores de visitas Note que os métodos executores de visitas são privados. Não se esqueça disso! Listagem 6 – O artesanais: executor de visitas que CalculaCustoProcedencia implementa para visitar produtos /** * doVisit * * @param produtoNatural ProdutoNatural * @return Double * @throws BusinessVisitException */ private Double doVisit(ProdutoNatural produtoNatural) throws BusinessVisitException { double percentualAdicionalProcedencia = 0; // Esse monte de if's são apenas para ilustração de regra de negócio. // NA VIDA REAL esses dados poderiam vir de uma fonte de dados qualquer. if (produtoNatural.getProcedencia().equals(Procedencia.AM)) { percentualAdicionalProcedencia = 20; } else if (produtoNatural.getProcedencia().equals(Procedencia.BA)) { percentualAdicionalProcedencia = 15; } else if (produtoNatural.getProcedencia().equals(Procedencia.RS)) { percentualAdicionalProcedencia = 10; } else if (produtoNatural.getProcedencia().equals(Procedencia.SP)) { percentualAdicionalProcedencia = 0; } double valorCustoProcedencia = ((produtoNatural.getValorCusto() / 100) * percentualAdicionalProcedencia); return new Double(valorCustoProcedencia); } Importante! O termo executor de visitas não consta em nenhuma outra estratégia de implementação de Visitor que eu conheço. Adotei esse termo porque a meu ver é o que mais descreve a função de um método doVisit. Quanto a VisitorHelper, ela é realmente a classe que aparenta ser: “apenas uma auxiliar de visitantes; nada mais que isso!”. Vejamos a Listagem 7. Listagem 7 – Código completo de VisitorHelper: package leandro.artigos.designpatterns.visitor; Grupo de Usuários Java – http://www.guj.com.br – Página 5 Clube Java http://www.clubejava.com.br import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * @author Leandro Silva * * @jug www.clubejava.com.br */ public class VisitorHelper { /** * doVisit * * @param visitorObject O Visitor que executará a visita * @param visitableObject O objeto que será visitado * @return Object O resultado da visita * @throws BusinessVisitException Exceção de negócios */ public static Object doVisit(Visitor visitorObject, Visitable visitableObject) throws BusinessVisitException { try { // Obtem o método executor de visitas. Se não existir: NoSuchMethodException! Method doVisit = visitorObject.getClass().getDeclaredMethod( "doVisit", new Class[] { visitableObject.getClass() } ); // Valida a assinatura do método Class exceptions[] = doVisit.getExceptionTypes(); if ((exceptions.length < 1 || exceptions.length > 1) || exceptions[0] != BusinessVisitException.class) { throw new BusinessVisitException("Invalid Visits Executor signature"); } // Como um executor de visitas é privado, torna-o acessivel doVisit.setAccessible(true); // Solicita a visita e retorna o resuldado return (Double)doVisit.invoke( visitorObject, new Object[] { visitableObject } ); } catch (NoSuchMethodException nsme) { throw new BusinessVisitException("This is not an valid visit"); } catch (InvocationTargetException ite) { throw new BusinessVisitException(ite.getCause().getMessage()); } catch (Exception e) { throw new BusinessVisitException(e); } } } VisitorHelper tem apenas o método estático doVisit, que simplesmente encontra o executor de visitas apropriado para a classe a ser visitada e o invoca solicitando a visita – ele é um proxy inteligente. Uma grande vantagem em utilizarmos VisitorHelper – além de não termos que codificar em todos os nossos visitantes o acesso aos executores de visitas via reflexão ou if’s encadeados – é que padronizamos a assinatura dos executores de visitas dos nossos visitantes. Mais visitantes, mais problemas resolvidos Um problema já foi resolvido, aleluia! Mas ainda temos outro. (ainda bem que descobrimos que visitantes especialistas de negócio podem nos ajudar a solucionar nossos problemas – e do nosso cliente, o que é melhor!). Grupo de Usuários Java – http://www.guj.com.br – Página 6 Clube Java http://www.clubejava.com.br Vamos escolher o visitante CalculaValorProdutoLoja como base para a solução do nosso problema 2, já que esse é o veículo trivial de venda da Quatro Cantos. CalculaValorProdutoLoja é um visitante que tem uma tarefa um pouco mais simples, pois o calculo do valor do produto não tem tanta especialização quanto o calculo de custo de procedência. Aliás, o visitante CalculaCustoProcedencia presta uma boa “consultoria” a CalculaValorProdutoLoja nesse sentido. Listagem 8 – O código que CalculaValorProdutoLoja implementa para visitar um produto: /** * visit * * @see Visitor#visit(leandro.artigos.designpatterns.visitor.Visitable) */ public Object visit(Visitable visitableObject) throws BusinessVisitException { Produto produtoLoja = (Produto)visitableObject; // Vamos utilizar um outro visitor para calcular o valor da custo de procedencia Double valorCustoProcedencia = (Double)produtoLoja.accept(new CalculaCustoProcedencia()); // Valor final para venda! double valorVenda = produtoLoja.getValorCusto() + valorCustoProcedencia.doubleValue(); return new Double(valorVenda); } Como podemos ver na Listagem 8, o trabalho que CalculaValorProdutoLoja realiza é realmente mais simples que o que CalculaCustoProcedencia realiza, pois a regra de calculo não é diferenciada para cada tipo de produto. Quando utilizar a estratégia executor de visitas? Só utilizaremos executores de visitas quando tivermos que aplicar regras de negócio diferenciadas para cada classe que desejemos que nosso componente de negócios (visitante) visite, como é o caso do visitante CalculaCustoProcedencia (Listagens 5 e 6). O visitante CalculaValorProdutoFone segue a CalculaValorProdutoLoja. Confira a listagem abaixo: mesma estrutura de implementação Listagem 9 – O código que CalculaValorProdutoFone implementa para visitar um produto: /** * visit * * @see Visitor#visit(leandro.artigos.designpatterns.visitor.Visitable) */ public Object visit(Visitable visitableObject) throws BusinessVisitException { Produto produtoFone = (Produto)visitableObject; // Vamos utilizar um outro visitor para calcular o valor da custo de procedencia Double valorCustoProcedencia = (Double)produtoFone.accept(new CalculaCustoProcedencia()); // Mais 2.5% adicional pelo produtos ser vendido pelo telefone double valorAdicionalFone = ((produtoFone.getValorCusto() / 100) * 2.5); int hora = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); // Se for entre meia-noite e cinco da manhã, cobramos adicional noturno: R$ 5,00 if (hora >= 0 && hora <= 5) { valorAdicionalFone += 5; } // E, finalmente, temos o valor final para venda! double valorVenda = produtoFone.getValorCusto() + valorAdicionalFone + valorCustoProcedencia.doubleValue(); return new Double(valorVenda); } Grupo de Usuários Java – http://www.guj.com.br – Página 7 de Clube Java http://www.clubejava.com.br Mais que visitante A essa altura do nosso estudo, depois de vermos tudo que um visitante é capaz de fazer, dada a sua especialidade em regras de uma fatia do nosso negócio, acho que sou capaz de arriscar chamá-los de consultores de negócio! Recebendo nossos visitantes Agora que já temos nossas classes visitáveis e nossos visitantes, vamos promover um encontro entre eles. A classe CatalogoProdutos é quem promove esse encontro. Qual a sua finalidade? “Listar todos os produtos cadastrados, calculando seus respectivos valores de venda, tanto através da Loja quanto da Central Telefônica”. Listagem 10 – O código que CatalogoProdutos implementa para listar produtos: /** * listarProdutos */ public void listarProdutos() { Produto produto; CalculaValorProdutoLoja calcularValorProdutoLoja = new CalculaValorProdutoLoja(); CalculaValorProdutoFone calcularValorProdutoFone = new CalculaValorProdutoFone(); System.out.println("*** QUATRO CANTOS - Catalogo de 'Preço de Venda' de Produtos ***"); System.out.println(); for (Iterator produtosIt = produtos.iterator(); produtosIt.hasNext();) { produto = (Produto)produtosIt.next(); System.out.println("- " + produto); try { System.out.println(" Loja R$ " + produto.accept(calcularValorProdutoLoja)); } catch (Exception e) { System.out.println("(!) LOJA - Ocorreu uma exceção de negócio: " + e.getMessage()); } try { System.out.println(" Fone R$ " + produto.accept(calcularValorProdutoFone)); } catch (Exception e) { System.out.println("(!) FONE - Ocorreu uma exceção de negócio: " + e.getMessage()); } System.out.println(); } } Como podemos ver na Listagem 10, o trabalho que CatalogoProdutos realiza para promover o encontro entre nossos produtos e nossos visitantes é de fato muito simples: basta solicitar que um produto aceite a visita de um visitante. Fixando o conhecimento Para que uma classe visitável aceite um visitante: classeVisitavel.accept(visitante); Problemas resolvidos: 10 a 0 para nós! Que ótimo, não? Esse é um belo placar, não é? É, mas devemos muito desse nosso sucesso a ajuda de nossos amigos Visitors na implementação de componentes de regras de negócio plugáveis. Sem eles, o que seria de nosso projeto? (Tudo bem, talvez não fosse tão ruim assim). Grupo de Usuários Java – http://www.guj.com.br – Página 8 Clube Java http://www.clubejava.com.br Mas, falando em projeto, nosso cliente, a Quatro Cantos, havia deixado claro que gostaria de entrar na onda dos negócios eletrônicos e começar a comercializar seus produtos pelo seu site na web. E, bem, enquanto desenvolvíamos nosso aplicativo, ele decidiu que quer que isso se torne realidade “ontem” – como todo bom cliente faria, é claro... Acho que essa é uma boa oportunidade de provarmos no fogo a nossa solução Visitor para saber se ela realmente é “plugável” ou se teremos que fazer algumas “alteraçõezinhas” em nossas classes visitáveis (no caso, nosso produtos). Um novo visitante para nos ajudar Como vimos no tópico “Mais visitantes, mais problemas resolvidos”, nosso aplicativo possui componentes visitantes responsáveis por calcular o valor de venda de determinado produto em determinado veículo de comercio (Loja ou Central Telefônica). Veremos a seguir a implementação de CalculaValorProdutoWeb, que como o próprio nome sugere, será o nosso consultor de negócio que detêm o conhecimento necessário para calcular o preço de venda de um produto na Web. Listagem 11 – A implementação completa de CalculaValorProdutoWeb: package leandro.artigos.designpatterns.visitor.produtos; import leandro.artigos.designpatterns.visitor.BusinessVisitException; import leandro.artigos.designpatterns.visitor.Visitable; import leandro.artigos.designpatterns.visitor.Visitor; /** * @author Leandro Silva * * @jug www.clubejava.com.br */ public class CalculaValorProdutoWeb implements Visitor { /** * visit * * @see Visitor#visit(leandro.artigos.designpatterns.visitor.Visitable) */ public Object visit(Visitable visitableObject) throws BusinessVisitException { Produto produtoWeb = (Produto)visitableObject; // Vamos utilizar um outro visitor para calcular o valor da custo de procedencia Double valorCustoProcedencia = (Double)produtoWeb.accept(new CalculaCustoProcedencia()); // Mais 10% adicional pelo produtos ser vendido pela web double valorAdicionalWeb = ((produtoWeb.getValorCusto() / 100) * 10); // E, finalmente, temos o valor final para venda! double valorVenda = produtoWeb.getValorCusto() + valorAdicionalWeb + valorCustoProcedencia.doubleValue(); return new Double(valorVenda); } } Como podemos ver na Listagem 11, CalculaValorProdutoWeb tem uma implementação bastante familiar aos seus companheiros CalculaValorProdutoLoja e CalculaValorProdutoFone, ou seja, apenas implementa o método visit (da interface Visitor), onde encontramos a regra de negócios para calcular o valor de venda do produto na Web. Agora, em nossa classe CatalogoProdutos, nosso método para listar produtos fica da seguinte maneira: Listagem 12 – A nova implementação de listarProdutos: /** * listarProdutos */ public void listarProdutos() { Produto produto; CalculaValorProdutoLoja calcularValorProdutoLoja = new CalculaValorProdutoLoja(); Grupo de Usuários Java – http://www.guj.com.br – Página 9 Clube Java http://www.clubejava.com.br CalculaValorProdutoFone calcularValorProdutoFone = new CalculaValorProdutoFone(); CalculaValorProdutoWeb calcularValorProdutoWeb = new CalculaValorProdutoWeb(); System.out.println("*** QUATRO CANTOS - Catalogo de 'Preço de Venda' de Produtos ***"); System.out.println(); for (Iterator produtosIt = produtos.iterator(); produtosIt.hasNext();) { produto = (Produto)produtosIt.next(); System.out.println("- " + produto); try { System.out.println(" Loja R$ " + produto.accept(calcularValorProdutoLoja)); } catch (Exception e) { System.out.println("(!) LOJA - Ocorreu uma exceção de negócio: " + e.getMessage()); } try { System.out.println(" Fone R$ " + produto.accept(calcularValorProdutoFone)); } catch (Exception e) { System.out.println("(!) FONE - Ocorreu uma exceção de negócio: " + e.getMessage()); } try { System.out.println(" Web R$ " + produto.accept(calcularValorProdutoWeb)); } catch (Exception e) { System.out.println("(!) WEB - Ocorreu uma exceção de negócio: " + e.getMessage()); } System.out.println(); } } O que visitantes podem fazer? Visitantes podem não somente utilizar dados de um visitável para processar regras de negócio, como também alterar seu estado. Exemplo: um visitante executa o préprocessamento de uma nota fiscal, altera vários atributos dessa nota fiscal e depois altera o status dessa nota fiscal para pré-processada; então, um outro visitante processa dados financeiros dessa nota fiscal e depois altera seu estado para faturada; e assim por diante. Quando executado, a saída de nosso aplicativo será algo semelhante a: *** QUATRO CANTOS - Catalogo de 'Preço de Venda' de Produtos *** - Produto: art001 Quadro de casca de coco Loja R$ 12.17475 Fone R$ 12.437249999999999 Web R$ 13.22475 - Produto: art002 Sapato de couro de jacaré Loja R$ 24.3 Fone R$ 24.8 Web R$ 26.3 - Produto: nat001 Moranguinho Loja R$ 0.11 Fone R$ 0.1125 Web R$ 0.12 - Produto: nat002 Chuva Loja R$ 1.12 Fone R$ 1.1480000000000001 Web R$ 1.2320000000000002 Grupo de Usuários Java – http://www.guj.com.br – Página 10 Clube Java http://www.clubejava.com.br Um visitante realmente especial! Já falamos tanto a respeito de visitantes que não poderia deixar de dizer que conheço Alguém realmente especial que gostaria muito de visitar a classe YourHeart (Apocalipse 3:20 – www.bibliaonline.com.br/read.jspa?book=66&chapter=3). Accept! Conclusão Vimos no decorrer desse tutorial o quanto Visitor pode nos ajudar na implementação de componentes de regras de negócio plugáveis. E como pudemos ver no tópico “Um novo visitante para nos ajudar”, é realmente muito simples implementar novos componentes e “pluga-los” em nosso aplicativo sem ter a necessidade de alterar a estrutura de classes existentes. Sugestões para fixação de conhecimento? Crie novas regras de negócio que podem ser agregadas a essa aplicação, utilizando o design pattern Visitor, e plugue-as nesse aplicativo. Isso o ajudará a fixar bem os conceitos estudados sobre Visitor. Até o próximo artigo! Leandro Silva ([email protected]) escreveu seu primeiro programa em Java no inicio de 1998 e, desde então, nunca mais parou! Atuou em analise, projeto e desenvolvimento de softwares corporativos, e-commerce e elearning em diversas empresas. Atualmente é pastor da Igreja Apostólica Renascer em Cristo (em Jardim Tranqüilidade, Guarulhos), desenvolvedor J2EE sênior na Convergence (www.convergence.com.br) e membro do JUG ClubeJava (www.clubejava.com.br). “Deus é Fiel”. Grupo de Usuários Java – http://www.guj.com.br – Página 11