UNIVERSIDADE FEDERAL DE SANTA CATARINA DEPARTAMENTO DE INFORMÁTICA E ESTATÍSTICA CURSO DE CIÊNCIAS DA COMPUTAÇÃO Framework para Camada de Apresentação Claudio Ulisses Nunes Biava Florianópolis 2004 UNIVERSIDADE FEDERAL DE SANTA CATARINA DEPARTAMENTO DE INFORMÁTICA E ESTATÍSTICA CURSO DE CIÊNCIAS DA COMPUTAÇÃO Framework para Camada de Apresentação Claudio Ulisses Nunes Biava Orientador: Raul Sidnei Wazlawick Banca Examinadora: João Bosco M. Sobral Mario Dantas Florianópolis 2004 Aquilo que não nos mata, nos faz mais forte. (Friedrich Nietzsche) A mente que se abre a uma nova idéia jamais volta ao seu tamanho original. (Albert Einstein) Agradeço aos meus pais pelo investimento, carinho e amor e confiança depositados em mim. Ao meu orientador por ter me aceito como seu orientando. Ao corpo docente pelo conhecimento a mim transmitido. Sumário Resumo ................................................................................................................................... 8 Abstract................................................................................................................................... 9 1. Apresentação .................................................................................................................. 1 1.1. Motivação ............................................................................................................... 1 1.2. Objetivos do Trabalho ............................................................................................ 1 1.3. Justificativa............................................................................................................. 2 2. Padrões de Projetos......................................................................................................... 3 2.1. Histórico ................................................................................................................. 3 2.2. Padrão Observador ................................................................................................. 4 2.3. Padrão Command ................................................................................................... 4 2.4. Padrão Template Method ....................................................................................... 5 2.5. Padrão Singleton..................................................................................................... 6 2.6. Padrão Arquitetural MVC(Model View Controller) .............................................. 6 2.6.1. Definições....................................................................................................... 7 2.6.2. Como funciona ............................................................................................... 8 3. Frameworks Orientados a Objetos ............................................................................... 10 3.1. Definição .............................................................................................................. 10 3.2. Qualidade de um bom Framework ....................................................................... 11 3.2.1. Generalidade................................................................................................. 11 3.2.2. Alterabilidade ............................................................................................... 12 3.2.3. Extensibilidade ............................................................................................. 12 3.2.4. Simplicidade ................................................................................................. 12 3.2.5. Clareza.......................................................................................................... 12 3.2.6. Fronteiras ...................................................................................................... 12 4. Estudo do Framework Struts ........................................................................................ 14 4.1. Projeto Jakarta ...................................................................................................... 14 4.2. Framework Struts ................................................................................................. 14 4.2.1. Introdução..................................................................................................... 14 4.2.2. Motivação para criação do Framework Struts.............................................. 15 4.2.3. Estrutura do Framework Struts..................................................................... 15 4.2.4. Como funciona o struts................................................................................. 16 4.2.5. Struts versus Framework Desenvolvido ....................................................... 17 5. Uso de Frameworks ...................................................................................................... 19 5.1. Indivíduos Envolvidos com o Desenvolvimento e Uso de Frameworks.............. 19 5.2. Questões-Chave para Usar um Framework .......................................................... 20 6. Framework Desenvolvido ............................................................................................ 22 6.1. As principais classes do Framework .................................................................... 22 6.2. Vantagens em usar o Framework ......................................................................... 22 6.3. Estrutura do Framework ....................................................................................... 23 6.3.1. Criação do model (modelo) .......................................................................... 24 6.3.2. Criação da view (visão) ................................................................................ 24 6.3.3. Criação da aplicação..................................................................................... 24 6.3.4. Criando um novo Controlador...................................................................... 25 Criando uma aplicação sob o Framework Bmvc.......................................................... 26 7.1. Criando a estrutura de diretórios .......................................................................... 26 7.2. Criando a aplicação .............................................................................................. 26 7.2.1. Criando a classe modelo ............................................................................... 26 7.2.2. Criando as Views.......................................................................................... 28 7.2.2.1. Criando a classe View Principal............................................................... 28 7.2.2.2. Criando a classe View EnqueteResultadoView ....................................... 31 7.2.3. Criando a classe Aplicação........................................................................... 33 8. Conclusão ..................................................................................................................... 36 9. Referências ................................................................................................................... 37 10. Anexo A – Artigo ..................................................................................................... 39 11. Anexo B – Código Fonte das Principais Classes...................................................... 44 7. Lista de Figuras Figura 1 – Aplicação sendo exibida por várias interfaces ...................................................... 7 Figura 2 - Fluxo de eventos e informações em uma arquitetura MVC .................................. 8 Figura 3 – MVC em nível de aplicação.................................................................................. 8 Figura 4 - Visão Conceitual da estrutura um Framework .................................................... 11 Figura 5 - Visão do framework Struts e do MVC. ............................................................... 15 Figura 6 – Struts e MVC ...................................................................................................... 16 Resumo Frameworks orientados a objetos promovem reuso de projeto e código. Contudo, a ampla adoção desta abordagem é dificultada pela complexidade para desenvolver e para usar frameworks. Este trabalho apresenta o framework Bmvc que é um framework para camada de apresentação baseado na arquitetura MVC (Model View Controller). Será abordado Design Patterns (Padrões de Projeto) que foram utilizados para desenvolver o framework. E finalmente será criado uma aplicação utilizando o framework Bmvc e explicando passo a passo como fazê-la. Palavras-Chaves: framework orientados a objetos, reuso, MVC, Design Patterns Abstract Object-oriented frameworks promote reuse design and code. However, the widespread adoption of this approach is made difficult by the complexity to develop and to use frameworks. This work presents the framework Bmvc that is a framework for presentation layer based on the architecture MVC (Model View Controller). It will be approach Design Patterns that were used to develop the framework. And finally will be created an application using framework Bmvc and explaining step by step as to make it. Keywords: Objects-oriented frameworks, reuse, MVC, Design Patterns. 1. Apresentação Este projeto é referente ao trabalho de conclusão do curso de Ciências da Computação da Universidade Federal de Santa Catarina. Este tem como propósito o desenvolvimento de um framework para camada de Apresentação. 1.1. Motivação O desenvolvimento de Frameworks se torna cada vez mais comum e necessário uma vez que existe uma necessidade de criar sistemas corporativos de modo mais rápido e a um baixo custo e de fácil manutenção. Framework é o esqueleto-base sobre o qual uma aplicação é construída, constituída de uma estrutura de classes com implementações incompletas, que estendidas permitem produzir novos aplicativos. A grande vantagem desta abordagem é a reutilização de código e projeto, que tem por intuito diminuir o tempo e o esforço no desenvolvimento de softwares. Este trabalho tem como objetivo implementar um framework para desenvolvimento de um Framework para Camada de Apresentação utilizando padrão arquitetural MVC (Model View Control). Seu desenvolvimento foi motivado pela necessidade de separar interface de código, ou seja, de se criar códigos de aplicações genéricos, não para interface especificas. 1.2. Objetivos do Trabalho Este trabalho tem como objetivo implementar um framework que facilite no desenvolvimento de aplicativos, uma vez que o projetista não vai precisar preocupar-se com a interação entre o modelo e a visão. Estudar e utilizar padrões de projetos para guiar na implementação de sua estrutura e relacionamento entre suas classes. O Framework Struts foi escolhido como objeto de estudo pois é um framework que implementa o Padrão Arquitetural MVC, padrão que foi implementado no framework desenvolvido. 1 1.3. Justificativa A principal justificativa para criação deste projeto é o fato de existirem poucas ferramentas que utilizam o padrão MVC, o que traz como conseqüência que desenvolvedores criem aplicações mal estruturas que muitas vezes é insuficiente para se ter um software de qualidade. Um grande benefício oferecido pelo padrão MVC é o fraco acoplamento caracterizado pela independência do modelo que representa as entidades do mundo real em relações a suas visões. Este fraco acoplamento permite um aumento de qualidade no aplicativo final desenvolvido. 2 2. Padrões de Projetos Nesta seção será dado um breve histórico dos Padrões de Projeto (Design Pattern), e apresentado em detalhes os padrões que foram utilizados no framework desenvolvido neste trabalho. 2.1. Histórico Nos anos setenta, Christopher Alexander escreveu vários livros relatando padrões na arquitetura e engenharia civil. A comunidade de software adotou a idéia de padrões baseada em seu trabalho, embora já existisse um crescente interesse nessas idéias por parte da comunidade. Os padrões de software foram popularizados com o livro Design Patterns: Elements of Reusable Object-Oriented Software de Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides (também conhecidos como Gang of Four, da onde veio à famosa sigla GoF). Salientando que os padrões que eles descrevem não foram inventados por eles. O que eles fizeram foi perceber que padrões se repetiam em numerosos projetos, eles identificaram e documentaram. Eles catalogaram 23 padrões. Dividos em: • Padrões de Criação: abstraem o processo de instanciação de objetos • Padrões Estruturais: definem a forma como as classes e objetos são compostos • Padrões Comportamentais: definem algoritmos e a atribuição de responsabilidades entre objetos. Os padrões se referem à comunicação de problemas e soluções. Em outras palavras, os padrões permitem documentar um problema que se repete e sua solução em um contexto especifico e comunicar esse conhecimento para outras pessoas. Algumas características comuns dos padrões são: • São observados através da experiência. • Evitam a reinvenção da roda. • Suportam melhorias continuas. • Podem ser utilizados em conjunto para resolver problemas maiores. 3 2.2. Padrão Observador Também conhecido como: Publisher-Subscriber, Event Generator, Dependents. O padrão Observador permite que objetos interessados sejam avisados da mudança de estado ou outros eventos ocorrendo num outro objeto. Com esse padrão parte da responsabilidade de processamento decorrente da mudança de estado de um objeto é distribuída a observadores. Também temos baixo acoplamento entre o objeto observado e os observadores. O objeto sendo observado é chamado de: • "Subject" (GoF) • "Observable" (java.util) • "Source" ou "Event Source" (java.swing e java.beans) • Provedor de informação (Bill Venners) • Gerador de eventos (Bill Venners) O objeto que observa é chamado de • Observer (GoF e java.util) • Listener (java.swing) Uma das motivações em utilizar esse padrão é que às vezes alterar um objeto requer mudanças em outros e não se sabe quantos objetos precisam ser mudados. No framework desenvolvido o objeto observado será o modelo e os objetos interessados nas suas mudanças serão as views. 2.3. Padrão Command O padrão Comando específica à definição de uma classe para cada mensagem ou comando, cada uma com um método execute. A chave para este padrão é uma classe abstrata Comando, que declara uma interface para execução de operações. Cada subclasse de Comando tem um único método execute que especifica as ações para aquele comando. Vantagens desse padrão: • Suportar “undo” (desfazer). A operação Execute do Comando pode armazenar o estado para reverter seus efeitos no próprio comando. A classe Comando deve 4 ter uma operação adicional “unexecute” que reverte os efeitos de uma chamada prévia para Execute. • Estruturar um sistema em volta de operações de alto nível construídas sobre operações primitivas. • O padrão Comando separa o objeto que invoca a operação daquele que sabe executá-la. • Permite que seja criado um “log” (registro) dos comandos que foram executados. Este padrão será utilizado pelo Controlador do framework em resposta aos eventos que ocorram nas views. A cada evento que ocorra nas interfaces será chamado um objeto comando responsável pela execução daquele evento. 2.4. Padrão Template Method Define o esqueleto de um algoritmo em uma operação, postergando alguns passos para subclasses. Esse padrão ilustra o Princípio de Hollywood: “não me chame, nos chamaremos você”. Um método template é um método que ao ser chamado invoca pelo menos um outro método chamado método hook. Método hook é um método gancho que fornece comportamento adicional ao método template. O método template comporta a parte imutável de um procedimento. A flexibilização do procedimento se da pelo overriding (sobrescrita) do(s) método(s) hook invocados. O padrão Template Method pode ser usado: • Para implementar as partes invariantes de um algoritmo uma só vez e deixar para as subclasses a implementação do comportamento que pode variar. • Para controlar extensões de subclasses. Você pode definir um método template que chama métodos ganchos (hook) em pontos específicos, desta forma permitindo extensões somente nestes pontos. 5 No framework desenvolvido o método template é o método que inicializa o framework, e os métodos hook são os métodos de criação do modelo e visão, que darão comportamento adicional ao método template. 2.5. Padrão Singleton O objetivo desse padrão é assegurar que uma classe tenha uma única instância e prover um ponto de acesso global a esta instância. Com ele é fácil fazer com que seja crie um número fixo, ou um número máximo de instâncias em vez de apenas uma única instância, apenas basta mudar implementação interna do Singleton. Este padrão foi utilizado para assegurar que a classe Aplicação do framework tem uma única instância e um ponto de acesso global a esta instância. 2.6. Padrão Arquitetural MVC(Model View Controller) Surgiu na comunidade de Smalltalk.A idéia é permitir que uma mesma lógica de negócios (modelo, model) possa ser acessada e visualizada através de várias interfaces (visão, view). Sua principal função é "separar" o sistema em 3 camadas, facilitando assim o entendimento, desenvolvimento e manutenção, deixando bem claras as funções desempenhadas por cada camada. O padrão MVC vem sendo amplamente usado em aplicações WEB, sendo principalmente implementada com o auxílio de frameworks entre estes se destacam o projeto "jakarta struts" que será discutido em frente, facilitando assim a criação de páginas dinâmicas de fácil manutenção e acelerado desenvolvimento. O conceito MVC também pode ser utilizado no desenvolvimento de aplicações desktop mantendo as mesmas vantagens citadas. Com as diversas possibilidades de interfaces que conhecemos hoje, a arquitetura MVC é uma ferramenta indispensável para desenvolvimento de aplicações mais complexas (Figura 1). 6 Figura 1 – Aplicação sendo exibida por várias interfaces 2.6.1. Definições Modelo (Model): contém os dados da aplicação junto com a lógica dos negócios que define como alterar e acessar os dados; o modelo pode ser compartilhado entre vários objetos, visões e controladores. O modelo é usado para gerenciar informações e notificar aos observadores quando esta informação sofre mudanças. O modelo encapsula mais do que somente dados e funções que operam sobre ele. Um modelo é feito para servir como uma aproximação de um modelo computacional, ou uma abstração de algum processo ou sistema do mundo real. Ele captura não somente o estado de um processo ou sistema, mas também com o sistema funciona. Na arquitetura MVC, o modelo não sabe de quantas nem quais interfaces com o usuário estão exibindo seu estado. Visão (View): é a forma de apresentação dos dados do modelo para o mundo externo, pode ser na forma de GUI (Graphical User Interface), fala, som, listagens ou mesmo em uma saída não orientada a usuários, como ligar um ar condicionado. Controlador (Controller): transforma eventos gerados pela interface em ações de negócio, alterando o modelo. . Por exemplo, se o usuário clica o botão do mouse ou 7 seleciona um item de menu, o controlador é o responsável por determinar como a aplicação deve responder. Na Figura 2 é ilustrado a interação destes três componentes: Figura 2 - Fluxo de eventos e informações em uma arquitetura MVC Figura 3 – MVC em nível de aplicação 2.6.2. Como funciona O modelo, a visão e o controlador são intimamente relacionados e estão constantemente se comunicando. Assim sendo, eles devem referenciar uns aos outros. A Figura 3 ilustra basicamente uma relação no estilo Model-View-Controller. 8 Ela mostra as linhas de comunicação dentre as camadas de modelo, visão e controlador. Na figura, o modelo aponta para a visão, que permite que ele envie notificações de alterações. Esta é só uma associação básica o modelo não deve estar ciente das visões que o observam, este baixo acoplamento é conseguido com o Padrão Observador. Em contraste a isto, a visão sabe exatamente que tipo de modelo ela está observando. A visão também tem uma associação de alto nível com o modelo, permitindo que ela chame qualquer outra função do mesmo. O controlador é o responsável por determinar como a aplicação deve responder em resposta as ações do usuário. 9 3. Frameworks Orientados a Objetos 3.1. Definição Um framework é uma aplicação quase completa, mas com pedaços faltando. Criar uma aplicação sob um framework consiste em prover os pedaços que são específicos para sua aplicação. Um framework provê uma solução para uma família de problemas semelhantes. Algumas definições de outros autores: “Framework é um esqueleto de implementação de uma aplicação ou um subsistema de aplicação, em um domínio de problema particular. É composto de classes abstratas e concretas e provê um modelo de interação ou colaboração entre as instancias de classes definidas pelo framework” [WIA 91]. “Um framework é utilizado através de configuração ou conexão de classes concretas e derivação de novas classes concretas a partir das classes abstratas do framework” [WIR 90]. “Um framework é um conjunto de classes inter-relacionadas com o objetivo de facilitar o desenvolvimento de um determinado domínio de aplicação. São compostas de classes concretas e abstratas, estas ultimas possuindo implementações incompletas que devem ser estendidas para compor as classes completas da aplicação final. A motivação para o desenvolvimento de frameworks é a reutilização de código e projeto, com o intuito de aumentar a produtividade no desenvolvimento de softwares” [SIR 00]. “Um framework captura as decisões de projeto que são comuns ao seu domínio de aplicação. Assim, frameworks enfatizam a reutilização de projeto em relação à reutilização de código, embora um framework, geralmente inclua subclasses concretas que o desenvolvedor pode utilizar imediatamente” [GAM 02]. O que trás como conseqüência que temos aplicações similares, que facilita no seu gerenciamento. Por outro lado, o desenvolvedor perde um pouco de liberdade uma vez que muitas decisões de projetos já foram tomas anteriormente. A diferença fundamental entre um framework e a reutilização de classes de uma biblioteca, é que neste caso as colaborações são criadas pela própria aplicação, cabendo ao desenvolvedor estabelecê-las. E no caso do framework, as colaborações estão embutidas. 10 Figura 4 - Visão Conceitual da estrutura um Framework 3.2. Qualidade de um bom Framework Para termos um bom Framework algumas características devem ser cumpridas: generalidade, alterabilidade e extensibilidade. Para que isto ocorra, o projeto do framework deve ser bem elaborado, buscando identificar que partes devem ser mantidas flexíveis para produzir um projeto bem estruturado. Desta forma, deve-se utilizar os princípios de um projeto orientado a objetos, como o uso da herança, polimorfismo, classes abstratas. 3.2.1. Generalidade Reflete a capacidade do framework em dar suporte a várias aplicações diferentes de um mesmo domínio, sendo flexível o suficiente para que as características de alterabilidade e extensibilidade possam ser aplicadas. 11 3.2.2. Alterabilidade Esta associada à capacidade do framework de alterar suas funcionalidades em função da necessidade de uma aplicação especifica sem que estas alterações resultem em conseqüências imprevistas no conjunto de sua estrutura. 3.2.3. Extensibilidade Reflete a capacidade do framework de ampliar sua funcionalidade sem conseqüências imprevistas no conjunto de sua estrutura. Ligada diretamente na manutenção do framework, permite que sua estrutura evolua. 3.2.4. Simplicidade A estrutura geral do framework deve ser de fácil compreensão de forma que o desenvolvedor possa aprendê-lo em pouco tempo. Esta simplicidade é alcançada pelo projeto de interfaces limpas e consistentes, pela utilização de padrões em seu projeto, código, interfaces e nomenclaturas. 3.2.5. Clareza Os aspectos comportamentais do framework devem ser encapsulados. Não há necessidade do desenvolvedor saber todos os detalhes do framework para que ele possa utilizá-lo. 3.2.6. Fronteiras Um framework tem responsabilidades claras e sucintas, e deve acatá-las e nada mais. Todas as funcionalidades exteriores a fronteira do framework devem ser tratadas pelo desenvolvedor. Quando um framework ultrapassa esta fronteira, ele se torna complexo e provavelmente o desenvolvedor ao tentar utilizá-lo precisará implementar código adicional junto a framework para conseguir o comportamento desejado. Um framework não prove a funcionalidade da aplicação, ele prove o esqueleto sobre o qual a aplicação é construída. 12 Caso o framework deseje prover classes mais especializadas, estas devem ser fornecidas em bibliotecas de classes separadas como subclasses das classes do framework. Isto permitirá ao desenvolvedor escolher usar ou não estas classes, fazendo assim uma clara distinção entre framework e o kit de ferramentas do desenvolvedor. 13 4. Estudo do Framework Struts Nesta seção será apresentado o Framework Struts, um framework que vem sendo amplamente utilizado em aplicações na WEB. Ele será apresentado por implementar o Padrão Arquitetural MVC, padrão que foi implementado no framework desenvolvido. 4.1. Projeto Jakarta O projeto Jakarta tem como objetivo criar e manter soluções de código aberto na Plataforma Java. Produtos de Jakarta são desenvolvidos e são distribuídos por vários subprojetos. Dentro destes subprojetos temos o Framework Struts. O projeto Jakarta é patrocinado por Apache Software Foundation. 4.2. Framework Struts 4.2.1. Introdução Struts foi criado por Craig R. McClanahan, e doado para Apache Software Foundation em Maio de 2000. O objetivo do Framework Struts é proporcionar um framework de código aberto para construção de aplicações web. O nome struts=suporte, que lembra partes que suportam construções, casas, pontes que são de certa forma “invisíveis” para as mesmas. Umas das principais características desse framework é que controle das camadas é baseado em tecnologias como Java Servlets, JavaBeans, ResourceBundles, e Extensible Markup Language (XML). Struts é baseado no padrão MVC (Model-View-Controller) Struts possui seu próprio componente controlador. Para o Modelo, Struts pode interagir com qualquer tecnologia padrão de acesso de dados, incluindo Enterprise Java Beans, JDBC, e Object Relational Bridge. Para Visão, struts pode utilizar JSP (JavaServer Pages), incluindo JSTL (JavaServer Standard Tag Library) e JSF (JavaServer Faces). 14 4.2.2. Motivação para criação do Framework Struts Muito claramente desenvolvedores perceberam que JSPs (JavaServer Pages) e servlets poderiam ser usados juntos para o desenvolvimento de aplicações web. Os servlets poderias ajudar no controle de fluxo, e o JSPs com a escrita do código HTML. O que deu origem ao Modelo Dois (usando JSPs e servlets juntos e JavaBeans) e no modelo 1(usava JSPs e JavaBeans), nas Figura 5 e Figura 6 vemos respectivamente a representações do Modelo 1 e do Modelo 2. 4.2.3. Estrutura do Framework Struts 7 Figura 5 - Visão do framework Struts e do MVC. Java Servlets: são projetados para manipular requisições feitas pelo Web browsers. Vantagens: • • • • • • Melhor que o padrão CGI (um dos primeiros mecanismos a permitir que um servidor WWW criasse conteúdo de forma dinâmica). Alta performance Conveniência Portabilidade Segurança Cria threads para cada requisição Web. 15 Java ServerPages são projetados para criar paginas Web dinâmicas. Struts usa Servlet como um controlador das requisições feitas pelo Web browsers para destinar para o ServerPage. Isto faz com que aplicações Web sejam mais fáceis de projetar, criar e alterar. Figura 6 – Struts e MVC Na Figura 6 temos um detalhamento maior do framework Struts juntamente com o MVC. 4.2.4. Como funciona o struts Num exemplo bem característico da arquitetura MVC, o framework struts, as views são renderizadas por arquivos jsps, sendo que o modelo, ou a “lógica de negócio” ficam com as classes Java e a parte do controle é praticamente todo implementada em um arquivo ”struts16 config.xml”, no qual são definidas as ações para determinadas requisições vindas do cliente. Os três componentes do MVC no struts: Model: é tudo que envolve o Business Logic, sem considerações de interface. JavaBeans (ou EJBs) são usados para Business Logic (Model). View: representa numa interface o estado corrente do Model. JSP são usados para representar a View. Struts ajuda a validar formulários com classes "Form". Controller: é usado para alimentar o Model quando ocorrem entradas na interface. O Controller é um servlet que já vem pronto em struts O que o Controller faz: Intercepta requests HTTP vindo de um cliente. Cada request recebe seu próprio thread. Traduz o request numa operação específica a ser feita. Chama a operação diretamente (ou delega para um Action Object). O servlet roteia o request para o destino correto (o objeto Action). Ajuda a selecionar a próxima View a mostrar para o cliente. Retorna a View para o cliente. 4.2.5. Struts versus Framework Desenvolvido No framework desenvolvido foi usado o padrão Arquitetural MVC do Smalltalk que usa o padrão de Notificação Observer, já no Struts é usado Modelo 2, também conhecido como: MVC2, Web MVC. Isso ocorre porque o padrão de notificação Observer não funciona bem em um ambiente web. O HTTP é um protocolo de “extração”: cliente solicita e o servidor responde. O padrão Observer requer um protocolo de anexação para a notificação, a fim de 17 que o servidor possa transferir uma mensagem para um cliente quando houver mudanças no modelo. Esse padrão funciona bem quando todos os recursos estão no mesmo servidor e os clientes têm uma conexão aberta com esse servidor. Não funciona bem tão bem quando os recursos são distribuídos em diversos servidores e os clientes não mantêm uma conexão aberta com a aplicação. 18 5. Uso de Frameworks Utilizar um framework consiste em criar aplicações a partir deste. A motivação para produzir aplicações a partir de frameworks é a perspectiva de aumento de qualidade e produtividade. Para produzir aplicações sob um framework deve-se estender sua estrutura. Um dos obstáculos em desenvolver uma aplicação sob um framework está no fato que um desenvolvedor de aplicações pode necessitar de um esforço superior para aprender a usar um framework que desenvolver sua aplicação do início ao fim. Para diminuir o esforço requerido pode-se criar ferramentas que auxiliem na compreensão de como usar framework. Como documentação no estilo cookbook. 5.1. Indivíduos Envolvidos com o Desenvolvimento e Uso de Frameworks “O desenvolvimento tradicional de aplicações envolve dois tipos de individuo: desenvolvedor de aplicação e usuário de aplicação (nos dois casos isto pode corresponder a grupos de indivíduos com diferentes funções). Desenvolvedores devem levantar os requisitos de uma aplicação, desenvolvê-la(o que inclui a documentação que ensina a usar a aplicação, como manuais de usuário) e entregá-la aos usuários. Usuários interagem com uma aplicação apenas através de sua interface.” “O desenvolvimento de frameworks introduz outro individuo, alem do desenvolvedor e usuário de aplicação: o desenvolvedor de framework. No contexto dos frameworks, o papel do usuário de aplicação é o mesmo descrito acima. O papel do desenvolvedor de aplicações difere do caso anterior pela inserção do framework no processo de desenvolvimento de aplicações. Com isto, o desenvolvedor de aplicações é para a produção de aplicações. Ele tem as mesmas funções do caso anterior: obter os requisitos da aplicação desenvolvê-la usando o framework, (o que em geral, não dispensa completamente do desenvolvedor de aplicações a necessidade de produzir código) e desenvolver a documentação da aplicação. O novo papel criado no contexto dos frameworks, o desenvolvedor de framework, tem a responsabilidade de produzir frameworks e algum modo de ensinar como usá-los para produzir aplicações”. [SIR 00]. 19 5.2. Questões-Chave para Usar um Framework Usuários de frameworks desenvolvidos segundo a abordagem caixa-preta ou black-box ou data-driven precisam apenas conhecer que objetos estão disponíveis e as regras para combiná-los. As instanciações e composições feitas determinam as particularidades da aplicação. No caso dos frameworks caixa-branca (white-box ou architecture-driven) e caixacinza, necessitam saber quais classes devem ser geradas, quais classes podem ser geradas, e precisam diferenciar os dois casos. Também necessitam conhecer quais as responsabilidades e as funcionalidades das classes a serem geradas. “Assim, no caso geral, as três questões-chave a seguir devem ser respondidas: Questão 1 – Quais classes? As classes concretas de uma aplicação podem ser criadas ou reutilizadas do framework. Então, que classes devem ser desenvolvidas pelo usuário e que classes concretas do framework podem ser reutilizadas? Questão 2 – Quais métodos? Um método de uma classe abstrata pode ser classificado como: - abstrato: um método que tem apenas a sua assinatura definida na classe abstrata; - template: é definido em termos de outros métodos (métodos hook); - base: é completamente definido. Na execução de um método template ocorre à chamada de pelo menos um método hook, que pode ser um método abstrato, base ou template. Ao produzir uma aplicação: - métodos abstratos precisam ser definidos; - métodos template fornecem uma estrutura de algoritmo definida, mas permitem flexibilidade através dos métodos hook chamados. A avaliação da necessidade ou conveniência de produção de métodos deve ser estendida para os métodos hook. - método base de acordo com o projeto do framework, não precisa ser alterado (mas é possível sobrepô-los). Assim ao gerar uma classe concreta para uma aplicação (considerando o caso de subclasse de classe abstrata do framework), que métodos devem ser definidos e que métodos herdados podem ser reutilizados? 20 Questão 3 – O que os métodos fazem?: Os métodos cuja estrutura deve ser definida pelo usuário do framework produzem o comportamento especifico da aplicação sob desenvolvimento. Assim, definidas as classes e os respectivos métodos a desenvolver, quais as responsabilidades destes métodos, em que situações de processamento eles atuam e como eles implementam a cooperação entre diferentes objetos?“ [SIR 00]. 21 6. Framework Desenvolvido O principal padrão de projeto utilizado nesse framework é o padrão MVC(Model View Controller) que tem o objetivo de separar a aplicação em três camadas. No framework modelo será a classe BmvcModel, a visão classe BmvcView, e o controlador a classe BmvcController. 6.1. As principais classes do Framework BmvcModel: responsável pelo modelo de dados. Esta classe deve ser extendida e implementada ao se criar uma aplicação sob o framework. BmvcView: responsável pela apresentação do dados. Para cada visão teremos uma subclasse da BmvcView. BmvcController: controla a aplicação. Para cada componente visual que gere eventos na interface deve ser implementado um controlador. Exemplo para controlador eventos que são gerados por botões deve ser implementado um controlador. A classe BmvcButtonCTRL implementa um controlador para botões. BmvcCommand: executa os eventos gerados na interface. BmvcAplic: classe a aplicação. 6.2. Vantagens em usar o Framework Para melhor expor as vantagens do uso do framework foi criado uma aplicação sem usá-lo, o código fonte se encontra no anexo. Entre elas temos que a arquitetura de camadas já está definida. Diminuindo o esforço do desenvolvedor uma vez que esta decisão já foi tomada, cabendo a ele seguí-la. Sem ter que se preocupar com colaborações entre as classes da aplicação, já que elas estão embutidas no framework. Por exemplo, o desenvolvedor não precisaria preocupar-se com interação entre modelo e visão, pois o próprio framework faz isso através do padrão MVC. Na aplicação sem o uso do framework ocorreu um forte acoplamento entre modelo e visão, visto que sempre que ocorrem alterações do modelo às visões devem ser notificadas dessas alterações o que trás como conseqüência que o modelo faça referência direta às visões. Porquanto muitas vezes 22 nem sabemos quais visões devem ser alteradas e tendo que novas visões poderiam ser criadas no futuro, toda vez que isso ocorre teríamos que mudar o modelo. Este fraco acoplamento permite um aumento de qualidade no aplicativo final desenvolvido. Com os controladores do framework não precisamos ter conhecimento sobre os controladores Swing do Java. Além que todos eventos dos controladores são executados pelo padrão Command que tem várias vantagens como: ele separa o objeto que invoca a operação daquele que sabe executá-la, a operação execute do padrão Command pode armazenar o estado para reverter seus efeitos no próprio comando, termos log dos comandos executados. Finalizando, se fosse criar uma aplicação sem o framework utilizando os padrões usados no framework teríamos consideravelmente um aumento de complexidade na aplicação. E o código não ficaria tão limpo quanto o código de uma aplicação desenvolvida sob o framework. Perderíamos em qualidade, tempo, esforço no desenvolvimento da mesma. 6.3. Estrutura do Framework O framework desenvolvido (Bmvc) foi feito na linguagem Java. Para desenvolver uma aplicação sob ele é necessário conhecimento básico na mesma. Para criar uma aplicação sob o Bmvc os seguintes passos devem ser seguidos, a seqüência é mais por motivos didáticos, mas não necessariamente precisa ser na ordem apresentada. 1) Criar o model (modelo) da aplicação 2) Criar a view (visão) ou as views da aplicação 3) Criar aplicação Note-se que apesar de estarmos usando o padrão MVC, não será necessário criar o Controlador, apenas será reutilizado os controladores que já vem com o framework. Sempre que houver necessidade pode-se facilmente criar novos controladores garantindo a extensibilidade do framework. 23 6.3.1. Criação do model (modelo) Para criar o modelo deve-se estender a classe BmvcModel, e nela deverá ser colocado apenas o que pertence ao Model sem nenhuma ligação com a View (apresentação dos dados). Para facilitar coloque o nome da classe como xxxModel.java. Essa classe é bem simples de definir a única coisa necessária é estender do framework a classe BmvcModel usando xxxModel extends BmvcModel. No construtor da classe inicialize os dados do modelo. 6.3.2. Criação da view (visão) Para criar a view estenda a classe BmvcView, a sua classe por padronização ficaria assim xxxView.java. Na view é necessário criar o método updateView, que será chamado pela classe BmvcView, toda a vez que a view for atualizada. No corpo desse método coloque o código que produz a alteração da View. Esse método ficaria assim: public void updateView() { ... } No construtor da classe deve-se pegar uma referência do modelo, está referência é conseguida pedindo para a aplicação o modelo (com temos baixo acoplamento), em seguida será mostrado a classe aplicação com mais detalhes. 6.3.3. Criação da aplicação Para criar a classe aplicação deve-se estender a classe BmvcAplic. O nome da sua classe aplicação pode ser MinhaAplicacao.java. Nessa classe será instanciado o modelo e todas as views. Métodos que devem ser definidos nessa classe: 1) public void criaModelo () { ... } esse é um método hook, que será chamado pela classe BmvcAplic. Nele deve ser instanciado o modelo e setado o modelo para que o framework saiba quem é o modelo da aplicação para isso use o método: setModel(seuModelo); 2) public void criaVisao () { ... } esse é um método hook, que será chamado pela classe BmvcAplic. Nele deve ser instanciado as views e adicionado as views para o framework , para isso use o método: addInternalFrame(suaView) 3) public static void main(String[] args) { … } 24 Aqui deve ser instanciado a própria classe aplicação no caso MinhaAplicacao, usando: MinhaAplicacao aplic = new MinhaAplicacao("Esta é a minha aplicação"). E em seguida showAplicacao(para mostrar a aplicação). 6.3.4. Criando um novo Controlador O framework já vem com alguns controladores prontos, mas é possível criar novos controladores. Para isso estenda a classe BmvcController, que é a classe controladora principal. No construtor chame o construtor da superclasse passando como parâmetros o componente para o qual está sendo criado o controlador e o comando que deve ser executado quando ocorre uma ação nesse componente. Para esse componente também é necessário adicionar um listener. Em seguida será mostrado um controlador em detalhes. 25 7. Criando uma aplicação sob o Framework Bmvc Nesse tópico será mostrado os principais pontos para criação de uma aplicação sob o framework Bmvc. A aplicação criada será de uma Enquete de Sistemas Operacionais.Algumas partes do código não será explicitada, todo o código da aplicação está no anexo do trabalho. 7.1. Criando a estrutura de diretórios Siga os passos abaixo para criar a estrutura de diretórios: 1) Inicialmente crie uma nova pasta (c:\minhaAplicacao); 2) Nessa pasta criada, coloque uma copia do framework Bmvc, nela constará três pastas: model, view, controller; 3) Agora cria outra pasta (c:\minhaAplicacao\Enquete) 4) Dentro dela cria as pastas: model, view, recursos Na pasta model ficará o modelo; Na pasta view as visões; Na pasta recursos ficará imagens, etc... 7.2. Criando a aplicação 7.2.1. Criando a classe modelo 1) Vá ao seu editor java e crie um novo arquivo e salve ele como: (C:\minhaAplicacao\aplicacao\enquete\model\ EnqueteModel.java) 2) Código comentado: //nome do seu pacote package enquete.model; //importação da classe BmvcModel do framework.model import framework.model.BmvcModel; 26 //estendendo a super classe Model public class EnqueteModel extends BmvcModel { //dados do modelo … public EnqueteModel() { //coloque aqui a inicialização do modelo } public void votar (String opcao) { //coloque aqui o código de quando ocorre um voto ... //notifica as view que houve mudança notifyViews(); } //outros métodos ... Na parte do modelo o que deve ser ressaltado é o método notifyViews() que informa as views que houve mudança. 27 7.2.2. Criando as Views Criaremos aqui duas views, no código em anexo foram criado quatro views. 7.2.2.1. Criando a classe View Principal Chamaremos de MainView a view principal. 1) Crie um novo arquivo no seu editor e salve (C:\minhaAplicacao\aplicacao\enquete\view\MainView.java). 2) Código comentado: //nome do seu pacote package aplicacao.enquete.view; //pacotes importados //utiliza o modelo para pegar os dados do mesmo e apresentá-los na tela import aplicacao.enquete.model.*; //aqui fica as imagens que são exibidas na tela, existe uma classe(Recursos.java) que captura o diretório onde as mesmas estão. import aplicacao.enquete.recursos.*; //utilizada para ter acesso à classe Aplicação que tem um ponto global de acesso(padrão Singleton), no anexo existe uma implementação simples desse padrão de projeto (SingletonPattern.java) ou na própria classe do framework (BmvcAplic.java). import framework.*; // utiliza os controladores que serão responsáveis por trocar informação entre a View e Model. import framework.controller.*; //superclasse view import framework.view.*; //estendendo a superclasse do framework 28 public class MainView extends BmvcView { … //a view tem uma referência ao modelo private EnqueteModel modelo; public MainView() { //pegando uma referencia do modelo modelo = (EnqueteModel) BmvcAplic.getModel(); // aqui é utilizado o padrão Observador. // O padrão Observador permite que objetos interessados sejam avisados // da mudança de estado ou outros eventos ocorrendo num outro objeto. No nosso caso //a view será notificada quando houve mudanças no modelo. modelo.addView(this); //menu principal para a view principal JMenu aplicacaoMenu = new JMenu("Aplicação"); aplicacaoMenu.setMnemonic('A'); //Padrão Command (no anexo a uma implementacao simples de padrão //CommandPattern.java) //note que aqui é criado o comando que será executado quando houver uma ação sobre, //esse caso será dado um voto no Sistema Operacional Windows. BmvcCommand cmdVotarWindows = new BmvcCommand () { public void execute(ActionEvent event) { modelo.votar("Windows"); } }; // submenus Aplicacao->Windows //aqui está sendo utilizado uns dos controladores do framework, e note que está sendo //passado para ele o comando que deve ser executado(cmdVotarWindows) quando 29 //houver um evento. BmvcMenuItemCTRL aplicacaoWindows = New BmvcMenuItemCTRL(aplicacaoMenu, "Windows", Recursos.getRecursos("win.gif"), 'W', "F2", cmdVotarWindows ); .... } 30 7.2.2.2. Criando a classe View EnqueteResultadoView Chamaremos de EnqueteResultadoView a view que mostrara a quantidade de votos. 1) Crie um novo arquivo no seu editor e salve (C:\minhaAplicacao\aplicacao\enquete\view\ EnqueteResultadoView.java). 2) Código comentado: // nome do seu pacote package aplicacao.enquete.view; //pacotes utilizados import aplicacao.enquete.model.*; import framework.*; import framework.view.*; ... public EnqueteResultadoView(int x, int y) { //pega uma referencia do modelo modelo = (EnqueteModel) BmvcAplic.getModel(); // aqui novamente é utilizado o padrão Observador. // O padrão Observador permite que objetos interessados sejam avisados // da mudança de estado ou outros eventos ocorrendo num outro objeto. No nosso caso //a view será notificada quando houve mudanças no modelo. modelo.addView(this); … } 31 // esse método será chamado pela classe BmvcView, toda a vez que a view for //atualizada. No corpo desse método coloca-se o código que produz a alteração //da View public void updateView() { .... } 32 7.2.3. 1) Vá Criando a classe Aplicação ao seu editor java e crie um novo arquivo e salve ele: (C:\minhaAplicacao\aplicacao\enquete\model\EnqueteModel.java) 2) Código comentado: // nome do seu pacote package aplicacao.enquete; //pacotes utilizados import aplicacao.enquete.model.*; import framework.*; import framework.model.*; import aplicacao.enquete.view.MainView; import aplicacao.enquete.view.EnqueteResultadoView; import aplicacao.enquete.view.EnqueteResultadoPorcView; import aplicacao.enquete.view.EnqueteResultadoGraficoView; //estendendo a superclasse do framework public class Enquete extends BmvcAplic { // construtor public Enquete(String name) { super(name, true, true); // aplicação criada com menu(segundo parâmetro) e toolbar(segundo parâmetro) } ... //aqui temos um método hook, que será chamada por um método template(Padrão //Template). Um método template é um método que ao ser chamado invoca pelo menos //um outro método chamado método hook. Método hook é um método gancho que 33 //fornece comportamento adicional ao método template. public void criaModelo() { // criar o modelo EnqueteModel modelo = new EnqueteModel(); // setado o modelo para que o framework saiba quem é o modelo da aplicação setModel( (BmvcModel) modelo); // povoa o modelo modelo.addItem("Linux"); modelo.addItem("Mac SO"); modelo.addItem("Windows"); }; //método hook public void criaVisao() { // cria as views mainView = new MainView(); enqueteResultadoView = new EnqueteResultadoView(20, 30); enqueteResultadoPorcView = new EnqueteResultadoPorcView(20, 190); enqueteResultadoGraficoView = new EnqueteResultadoGraficoView(255, 30); //adiciona as views ao framework BmvcAplic.addInternalFrame(enqueteResultadoView.getInternalFrame()); BmvcAplic.addInternalFrame(enqueteResultadoPorcView.getInternalFrame()); BmvcAplic.addInternalFrame(enqueteResultadoGraficoView.getInternalFrame()); }; //finalmente temos o método main, aqui é instanciado a classe Enquete. public static void main(String[] args) { 34 final Enquete termometro = new Enquete("Aplicação - Enquete de Sistemas Operacionais"); //mostra a aplicação. BmvcAplic.showAplicacao(); } } 35 8. Conclusão A abordagem de frameworks contribui significativamente para reutilização no desenvolvimento de artefatos de software. Frameworks é uma abordagem que está sendo cada vez mais utilizada, com o objetivo de diminuir o tempo e esforços no desenvolvimento de artefatos de software. Para se ter um bom projeto, este deve ser bem estruturado e planejado. Padrões de projeto ajudam o projetista no desenvolvimento de projetos melhor estruturados, oferecendo soluções que foram desenvolvidas e aperfeiçoadas ao longo do tempo. O framework desenvolvido permite a separação das camadas de dados, controle e visualização. Esta separação oferece vantagens para desenvolvedores como a otimização das habilidades de equipes e a redução de custos associados ao desenvolvimento, além de favorecer a extensibilidade e reutilização do código. Temos também o reuso de projeto e código proporcionado pelo framework. O fraco acoplamento do modelo de dados permite um aumento de qualidade no aplicativo final desenvolvido. Outro ponto é que o framework força o desenvolvedor a criar aplicações mais bem estruturadas. Para testar o framework foram criados para um mesma aplicação três versões da mesma: a primeira utilizando o framework, segunda sem usar o framework e sem padrões de projeto e a ultima sem usar o framework e usando padrões de projeto. Para as três versões a que teve menos linhas de códigos escritas e também levou menos tempo para desenvolver foi a utilizando o framework. 36 9. Referências [WIR 90] WIRFS-BROCK, R, Johnson, R. E. Surveying current research in object-oriented design. Communications of the ACM. V.33, n.9. sep. 1990. [WIA 91] WIRFS-BROCK, A. et. Al. Designing reusable designs: Experiences designing object-oriented frameworks. In: Object-Oriented Programming Systems, Languages and Applications Conference; European on Object-Oriented Programming, 1991. [SIR 00] SILVA, Ricardo P. Suporte ao desenvolvimento e uso de frameworks e componentes. Tese para a obtenção do grau de Doutor em Ciências da Computação. Universidade Federal do Rio Grande do Sul, UFRGS. Porto Alegre, 2000. [GAM 02] GAMMA, Eric, HELM, Richard, JOHNSON, Ralph, VLISSIDES, John. Padrões de Projeto: soluções reutilizáveis de software orientado a objetos. Porto Alegre: Bookman, 2002. LARMAN, Craig. Utilizando UML e padrões: Uma introdução à análise e ao projeto orientado a objetos. Tradução Luiz A. M. Salgado. Porto Alegre: Bookman, 2000. LARMAN, Craig.Applying UML and Patterns: A introduction to object-oriented analysis and design and the unified process. 2 ed: Prentice Hall, 2000. JAKARTA, Projeto Jakarta. Disponível em <http://jakarta.apache.org>. Acesso em 10 jun. 2003. STRUTS, Framework Struts. Disponível em <http://jakarta.apache.org/struts/>. Acesso em 11 jun. 2003. 37 JAVA WORLD, Exploring the MVC design pattern. Disponível em <http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html>. Acesso em 11 jun. 2003. HUSTED, Framework Struts. Disponível em <http://www.husted.com/struts/resources/struts-intro.ppt >. Acesso em 12 jun 2003. 38 10. Anexo A – Artigo Framework para Camada de Apresentação Claudio Ulisses Nunes Biava Departamento de Informática e Estatística – Universidade Federal de Santa Catarina (UFSC) [email protected] Resumo Frameworks orientados a objetos promovem reuso de projeto e código. Contudo, a ampla adoção desta abordagem é dificultada pela complexidade para desenvolver e para usar frameworks. Este trabalho apresenta o framework Bmvc que é um framework para camada de apresentação baseado na arquitetura MVC (Model View Controller). Será abordado Design Patterns (Padrões de Projeto) que foram utilizados para desenvolver o framework. E finalmente será criado uma aplicação utilizando o framework Bmvc e explicando passo a passo como fazê-la. Palavras-Chaves: framework orientados a objetos, reuso, MVC, Design Patterns Abstract Object-oriented frameworks promote reuse design and code. However, the widespread adoption of this approach is made difficult by the complexity to develop and to use frameworks. This work presents the framework Bmvc that is a framework for presentation layer based on the architecture MVC (Model View Controller). It will be approach Design Patterns that were used to develop the framework. And finally will be created an application using framework Bmvc and explaining step by step as to make it. Keywords: Objects-oriented frameworks, reuse, MVC, Design Patterns. 1. Introdução O desenvolvimento de Frameworks se torna cada vez mais comum e necessário uma vez que existe uma necessidade de criar sistemas corporativos de modo mais rápido e a um baixo custo e de fácil manutenção. Framework é o esqueleto-base sobre o qual uma aplicação é construída, constituída de uma estrutura de classes com implementações incompletas, que estendidas permitem 39 produzir novos aplicativos. A grande vantagem desta abordagem é a reutilização de código e projeto, que tem por intuito diminuir o tempo e o esforço no desenvolvimento de softwares. Este trabalho tem como objetivo implementar um framework para desenvolvimento de um Framework para Camada de Apresentação utilizando padrão arquitetural MVC (Model View Control), ou seja, separação de modelo e visão. Seu desenvolvimento foi motivado pela necessidade de separar interface de código, ou seja, de se criar códigos de aplicações genéricos, não para interface especificas. 2. Padrões de Projeto Os padrões de software foram popularizados com o livro Design Patterns: Elements of Reusable Object-Oriented Software de Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides (também conhecidos como Gang of Four, da onde veio à famosa sigla GoF). Salientando que os padrões que eles descrevem não foram inventados por eles. O que eles fizeram foi perceber que padrões se repetiam em numerosos projetos, eles identificaram e documentaram. Eles catalogaram 23 padrões. Dividos em: • Padrões de Criação: abstraem o processo de instanciação de objetos • Padrões Estruturais: definem a forma como as classes e objetos são compostos • Padrões Comportamentais: definem algoritmos e a atribuição de responsabilidades entre objetos. Os padrões se referem à comunicação de problemas e soluções. Em outras palavras, os padrões permitem documentar um problema que se repete e sua solução em um contexto especifico e comunicar esse conhecimento para outras pessoas. Nesse trabalho foram utilizados os seguintes padrões: Observador, Command, Template Method, Singleton, Padrão Arquitetural MVC 3. Padrão Arquitetural MVC Sua principal função é "separar" o sistema em 3 camadas, facilitando assim o entendimento, desenvolvimento e manutenção, deixando bem claras as funções desempenhadas por cada camada. O padrão MVC vem sendo amplamente usado em aplicações WEB, sendo principalmente implementada com o auxílio de frameworks entre estes se destacam o projeto "jakarta struts" que será discutido em frente, facilitando assim a criação de páginas dinâmicas de fácil manutenção e acelerado desenvolvimento. O conceito MVC também pode ser utilizado no desenvolvimento de aplicações desktop mantendo as mesmas vantagens citadas. Modelo (Model): contém os dados da aplicação junto com a lógica dos negócios que define como alterar e acessar os dados; o modelo pode ser compartilhado entre vários objetos, visões e controladores. 40 Visão (View): é a forma de apresentação dos dados do modelo para o mundo externo, pode ser na forma de GUI (Graphical User Interface), fala, som, listagens ou mesmo em uma saída não orientada a usuários, como ligar um ar condicionado. Controlador (Controller): transforma eventos gerados pela interface em ações de negócio, alterando o modelo. . Por exemplo, se o usuário clica o botão do mouse ou seleciona um item de menu, o controlador é o responsável por determinar como a aplicação deve responder. 4. Frameworks Orientados a Objetos Um framework é uma aplicação quase completa, mas com pedaços faltando. Criar uma aplicação sob um framework consiste em prover os pedaços que são específicos para sua aplicação. Um framework provê uma solução para uma família de problemas semelhantes. 5. Qualidade de um bom Framework Para termos um bom Framework algumas características devem ser compridas: generalidade, alterabilidade e extensibilidade. Para que isto ocorra, o projeto do framework deve ser bem elaborado, buscando identificar que partes devem ser mantidas flexíveis para produzir um projeto bem estruturado. Desta forma, deve-se utilizar os princípios de um projeto orientado a objetos, como o uso da herança, polimorfismo, classes abstratas. Características de um bom framework: Generalidade, Alterabilidade, Extensibilidade, Simplicidade, Clareza, Fronteiras. 6. Framework Desenvolvido O principal padrão de projeto utilizado nesse framework é o padrão MVC(Model View Controller) que tem o objetivo de separar a aplicação em três camadas. No framework modelo será a classe BmvcModel, a visão classe BmvcView, e o controlador a classe BmvcController. As principais classes do Framework: BmvcModel: responsável pelo modelo de dados. Esta classe deve ser extendida e implementada ao se criar uma aplicação sob o framework. BmvcView: responsável pela apresentação do dados. Para cada visão teremos uma subclasse da BmvcView. BmvcController: controla a aplicação. Para cada componente visual que gere eventos na interface deve ser implementado um controlador. Exemplo para controlador eventos que são gerados por botões deve ser implementado um controlador. A classe BmvcButtonCTRL implementa um controlador para botões. BmvcCommand: executa os eventos gerados na interface. BmvcAplic: classe a aplicação. 41 Entre as vantagens do framework temos que a arquitetura de camadas já está definida. Diminuindo o esforço do desenvolvedor uma vez que esta decisão já foi tomada, cabendo a ele seguí-la. Sem ter que se preocupar com colaborações entre as classes da aplicação, já que elas estão embutidas no framework. Com os controladores do framework não precisamos ter conhecimento sobre os controladores Swing do Java. Além que todos eventos dos controladores são executados pelo padrão Command que tem várias vantagens como: ele separa o objeto que invoca a operação daquele que sabe executá-la, a operação execute do padrão Command pode armazenar o estado para reverter seus efeitos no próprio comando, termos log dos comandos executados. Finalizando, se fosse criar uma aplicação sem o framework utilizando os padrões usados no framework teríamos consideravelmente um aumento de complexidade na aplicação. E o código não ficaria tão limpo quanto o código de uma aplicação desenvolvida sob o framework. Perderíamos em qualidade, tempo, esforço no desenvolvimento da mesma. O framework desenvolvido (Bmvc) foi feito na linguagem Java. Sendo assim para criar uma aplicação sob ele é necessário conhecimento básico na mesma. Para criar uma aplicação sob o Bmvc os seguintes passos devem ser seguidos, a seqüência dos passos é mais por motivos didáticos, mas não necessariamente precisa ser na ordem apresentada. 1. Criar o model (modelo) da aplicação 2. Criar a view (visão) ou as views da aplicação 3. Criar aplicação Note-se que apesar de estarmos usando o padrão MVC, não será necessário criar o Controlador, apenas será reutilizado os controladores que já vem com o framework. Sendo que se houver necessidade pode-se facilmente criar novos controladores garantindo a extensibilidade do framework. 7. Conclusão O framework desenvolvido permite a separação das camadas de dados, controle e visualização. Esta separação oferece vantagens para desenvolvedores como a otimização das habilidades de equipes e a redução de custos associados ao desenvolvimento, além de favorecer a extensibilidade e reutilização do código. Temos também o reuso de projeto e código proporcionado pelo framework, O fraco acoplamento do modelo de dados permite um aumento de qualidade no aplicativo final desenvolvido. Outro ponto é que o framework força o desenvolvedor a criar aplicações mais bem estruturadas. Para testar o framework foram criados para um mesma aplicação três versões da mesma: a primeira utilizando o framework, segunda sem usar o framework e sem padrões de projeto e a ultima sem usar o framework e usando padrões de projeto. Para as três versões a que teve menos linhas de códigos escritas e também levou menos tempo para desenvolver foi a utilizando o framework. 42 8. Referências [WIR 90] WIRFS-BROCK, R, Johnson, R. E. Surveying current research in object-oriented design. Communications of the ACM. V.33, n.9. sep. 1990. [WIA 91] WIRFS-BROCK, A. et. Al. Designing reusable designs: Experiences designing object-oriented frameworks. In: Object-Oriented Programming Systems, Languages and Applications Conference; European on Object-Oriented Programming, 1991. [SIR 00] SILVA, Ricardo P. Suporte ao desenvolvimento e uso de frameworks e componentes. Tese para a obtenção do grau de Doutor em Ciências da Computação. Universidade Federal do Rio Grande do Sul, UFRGS. Porto Alegre, 2000. [GAM 02] GAMMA, Eric, HELM, Richard, JOHNSON, Ralph, VLISSIDES, John. Padrões de Projeto: soluções reutilizáveis de software orientado a objetos. Porto Alegre: Bookman, 2002. LARMAN, Craig. Utilizando UML e padrões: Uma introdução à análise e ao projeto orientado a objetos. Tradução Luiz A. M. Salgado. Porto Alegre: Bookman, 2000. LARMAN, Craig.Applying UML and Patterns: A introduction to object-oriented analysis and design and the unified process. 2 ed : Prentice Hall, 2000. JAKARTA, Projeto Jakarta. Disponível em <http://jakarta.apache.org>. Acesso em 10 jun. 2003. STRUTS, Framework Struts. Disponível em <http://jakarta.apache.org/struts/>. Acesso em 11 jun. 2003. JAVA WORLD, Exploring the MVC design pattern. Disponível em <http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html>. Acesso em 11 jun. 2003. HUSTED, Framework Struts. Disponível em <http://www.husted.com/struts/resources/struts-intro.ppt >. Acesso em 12 jun 2003. 43 11. Anexo B – Código Fonte das Principais Classes Classe - BmvcModel.java /* * BmvcModel - a superclasse modelo(MVC) para o framework Bmvc */ package framework.model; import java.util.*; import framework.view.BmvcView; public class BmvcModel extends Observable { // Observable usada para implementação do padrão Observador // O padrão Observador permite que objetos interessados sejam avisados // da mudança de estado ou outros eventos ocorrendo num outro objeto. public BmvcModel() { super(); } public void addView(BmvcView view) { addObserver( (Observer) view); //método addObserver faz parte da classe Observable } public void deleteView(BmvcView view) { deleteObserver( (Observer) view); //método deleteObserver faz parte da classe Observable } public void notifyViews() { setChanged(); notifyObservers(); } } Classe - BmvcView.java /* 44 * BmvcView - a superclasse view(MVC) para o framework Bmvc */ package framework.view; import java.util.*; public class BmvcView implements Observer { // implementação da interface Observer public void update(Observable observed, Object value) { updateView(); } public void updateView() { } } Classe - BmvcController.java /* * BmvcController - implementação de um Controlador genérico usando o padrão Comando * para o framework Bmvc, simplifica os controles do Swing */ package framework.controller; import java.awt.event.*; import javax.swing.*; import java.awt.event.WindowEvent; public class BmvcController implements ActionListener,ItemListener,AdjustmentListener { protected JComponent componente; private BmvcCommand BmvcCommand; // objeto executor public BmvcController(JComponent comp, String tip, BmvcCommand bExec) { componente = comp; BmvcCommand = bExec; if (tip != null) { 45 componente.setToolTipText(tip); } } public BmvcCommand getBmvcCommand() { return BmvcCommand; } /* * Implementação dos Listeners para os componentes. * Cada listener enviará uma mensagem apropriada ao método execute que está associado ao BmvcCommand. O tipo de evento determina a assinatura do método execute. */ // implementa o ActionListener public void actionPerformed(ActionEvent event) { if (BmvcCommand != null) { BmvcCommand.execute(event); } } // implementa o ItemListener public void itemStateChanged(ItemEvent event) { if (BmvcCommand != null) { BmvcCommand.execute(event); } } // implementa o AdjustmentListener public void adjustmentValueChanged(AdjustmentEvent event) { if (BmvcCommand != null) { BmvcCommand.execute(event); } } /* public void windowClosing(WindowEvent event) { if (BmvcCommand != null) { BmvcCommand.execute(event); } }*/ } Classe - BmvcCommand.java 46 /* * BmvcCommand - Classe suporte para implementação do BmvcController * seguindo o Padrão Command */ package framework.controller; import java.awt.event.*; import javax.swing.event.*; public abstract class BmvcCommand { // um execute para cada tipo de evento que existir. public void execute(ActionEvent event) { } public void execute(ItemEvent event) { } public void execute(ChangeEvent event) { } public void execute(AdjustmentEvent event) { } public void execute(WindowEvent event) { } } Classe - BmvcScrollbarCTRL.java /* * BmvcScrollbarCTRL - implementa o controle para JScroolBar */ package framework.controller; import javax.swing.*; import framework.BmvcAplic; public class BmvcScrollbarCTRL 47 extends BmvcController { private JScrollBar scrollBar; public BmvcScrollbarCTRL(String tip, boolean horizontal, BmvcCommand bExec) { super ( (JComponent)new JScrollBar(horizontal? JScrollBar.HORIZONTAL: JScrollBar.VERTICAL, 0, 10,-46, 160), tip, bExec); scrollBar = (JScrollBar) componente; scrollBar.addAdjustmentListener(this); // adiciona o listener } public JScrollBar getJScrollBar() { return scrollBar; } } Classe - BmvcButtonCTRL.java /* * BmvcButtonCTRL - implements JButton controller for Jbutton */ package framework.controller; import javax.swing.*; import framework.BmvcAplic; import java.net.URL; public class BmvcButtonCTRL extends BmvcController { private JButton botao; // construtor public BmvcButtonCTRL(String text, URL icon, String tip, BmvcCommand bExec) { super( (JComponent)new JButton(), tip, bExec); botao = (JButton) componente; if (text != null) { 48 botao.setText(text); } if (icon != null) { Icon icone = new ImageIcon(icon); botao.setIcon(icone); } botao.addActionListener(this); // adiciona o listener BmvcAplic.getToolBar().add(botao); } public JButton getJButton() { return botao; } } Classe - BmvcMenuItemCTRL.java /* * BmvcMenuItemCTRL - implementa o controle para JMenuItem */ package framework.controller; import java.net.*; import javax.swing.*; public class BmvcMenuItemCTRL extends BmvcController { private JMenu menu; private JMenuItem menuItem; //construtor public BmvcMenuItemCTRL(JMenu menu, String texto, URL icon, char mnemonic, String atalho, BmvcCommand bExec) { super( (JComponent)new JMenuItem(), texto, bExec); menu = menu; menuItem = (JMenuItem) componente; 49 if (texto != null) { menuItem.setText(texto); } if (mnemonic != ' ' && mnemonic != 0) { menuItem.setMnemonic(mnemonic); } if (atalho != null) { KeyStroke ks = KeyStroke.getKeyStroke(atalho); menuItem.setAccelerator(ks); } if (icon != null) { Icon icone = new ImageIcon(icon); menuItem.setIcon(icone); } menuItem.addActionListener(this); // adiciona o listener menu.add(menuItem); } public JMenu getJMenu() { return menu; } public JMenuItem getJMenuItem() { return menuItem; } } Classe - BmvcWindowCTRL.java package framework.controller; import javax.swing.*; import framework.BmvcAplic; import java.awt.event.WindowAdapter; import java.awt.event.WindowListener; import java.awt.event.WindowEvent; public class BmvcWindowCTRL extends BmvcController { private JScrollBar scrollBar; private WindowListener window; 50 public BmvcWindowCTRL(String tip, BmvcCommand bExec) { super( (JComponent)new JScrollBar(JScrollBar.HORIZONTAL, 0, 10,-46, 160), tip, bExec); scrollBar = (JScrollBar) componente; scrollBar.addAdjustmentListener(this); // add listener new WindowAdapter() { public void windowClosing(WindowEvent e) { BmvcAplic.getAplic().aplicacaoClose(); } }; } /* new WindowAdapter() { public void windowClosing(WindowEvent e) { BmvcAplic.getAplic().aplicacaoClose(); System.exit(0); } }; */ } Classe - Enquete.java /* * Enquete - Aplicação teste para Framework Bmvc */ package aplicacao.enquete; import aplicacao.enquete.model.*; import framework.*; import framework.model.*; import aplicacao.enquete.view.MainView; import aplicacao.enquete.view.EnqueteResultadoView; import aplicacao.enquete.view.EnqueteResultadoPorcView; import aplicacao.enquete.view.EnqueteResultadoGraficoView; public class Enquete extends BmvcAplic { 51 private MainView mainView; private EnqueteResultadoView enqueteResultadoView; private EnqueteResultadoPorcView enqueteResultadoPorcView; private EnqueteResultadoGraficoView enqueteResultadoGraficoView; // construtor public Enquete(String name) { super(name, true, true); // criado com menu e toolbar } public static void main(String[] args) { final Enquete termometro = new Enquete("Aplicação - Enquete de Sistemas Operacionais"); BmvcAplic.showAplicacao(); } //método hook public void criaModelo() { // criar o modelo EnqueteModel modelo = new EnqueteModel(); setModel( (BmvcModel) modelo); // povoa o modelo modelo.addItem("Linux"); modelo.addItem("Mac SO"); modelo.addItem("Windows"); }; //método hook public void criaVisao() { // criar view/controlador mainView = new MainView(); enqueteResultadoView = new EnqueteResultadoView(20, 30); enqueteResultadoPorcView = new EnqueteResultadoPorcView(20, 190); enqueteResultadoGraficoView = new EnqueteResultadoGraficoView(255, 30); BmvcAplic.addInternalFrame(enqueteResultadoView.getInternalFrame()); BmvcAplic.addInternalFrame(enqueteResultadoPorcView.getInternalFrame()); BmvcAplic.addInternalFrame(enqueteResultadoGraficoView.getInternalFrame()); }; } 52 Classe - EnqueteModel.java /* * EnqueteModel - implementação do modelo */ package aplicacao.enquete.model; import framework.model.BmvcModel; import java.util.HashMap; import java.util.Map; import java.util.Iterator; public class EnqueteModel extends BmvcModel { //dados do modelo private Map dados; private int nDados; public EnqueteModel() { dados = new HashMap(); nDados = 0; } public void addItem(String descricao) { dados.put(descricao, new Integer(0)); nDados++; } public void setVotos(String opcao, int votos) { dados.put(opcao, new Integer(votos)); notifyViews(); //notifica as view que houve mudança } public void votar(String opcao) { int votoAtual = ( (Integer) dados.get(opcao)).intValue(); dados.put(opcao, new Integer(++votoAtual)); notifyViews(); //notifica as view que houve mudança } public int getVotos(String opcao) { return ( (Integer) dados.get(opcao)).intValue(); } public Float getVotosEmPorc(String opcao) { 53 Float r = new Float(0); float valor = ( (Integer) dados.get(opcao)).floatValue(); int total = getTotalVotos(); if (total > 0) { r = new Float(valor / total); } return r; } public Iterator getItens() { return dados.keySet().iterator(); } public int getTotalVotos() { Iterator votos = dados.values().iterator(); int total = 0; while (votos.hasNext()) { total = total + ( (Integer) votos.next()).intValue(); } return total; } public int getNDados() { return nDados; } } Classe - MainView.java /* * MainView - View para Enquete */ package aplicacao.enquete.view; import java.awt.event.*; import javax.swing.*; import aplicacao.enquete.model.*; import aplicacao.enquete.recursos.*; import framework.*; 54 import framework.controller.*; import framework.view.*; public class MainView extends BmvcView { private EnqueteModel modelo; public MainView() { modelo = (EnqueteModel) BmvcAplic.getModel(); modelo.addView(this); JMenu aplicacaoMenu = new JMenu("Aplicação"); aplicacaoMenu.setMnemonic('A'); // Aplicacao->Windows BmvcCommand cmdVotarWindows = new BmvcCommand() { public void execute(ActionEvent event) { modelo.votar("Windows"); } }; BmvcMenuItemCTRL aplicacaoWindows = new BmvcMenuItemCTRL(aplicacaoMenu, "Windows", Recursos.getRecursos("win.gif"), 'W', "F2", cmdVotarWindows ); // Aplicacao->Mac BmvcMenuItemCTRL aplicacaoMac = new BmvcMenuItemCTRL(aplicacaoMenu, "Mac SO", Recursos.getRecursos("mac.gif"), 'M', "F3", new BmvcCommand() { public void execute(ActionEvent event) { modelo.votar("Mac SO"); } }); // Aplicacao->Linux BmvcMenuItemCTRL aplicacaoLinux = new BmvcMenuItemCTRL(aplicacaoMenu, "Linux", Recursos.getRecursos("linux.gif"), 'L', "F4", new BmvcCommand() { public void execute(ActionEvent event) { 55 modelo.votar("Linux"); } }); // Aplicacao=>Sair BmvcMenuItemCTRL aplicacaoSair = new BmvcMenuItemCTRL(aplicacaoMenu, "Sair", Recursos.getRecursos("sair.gif"), 'S', "F12", new BmvcCommand() { public void execute(ActionEvent event) { BmvcAplic.getAplic().aplicacaoClose(); } }); BmvcAplic.addMenu(aplicacaoMenu); BmvcButtonCTRL btWindows = new BmvcButtonCTRL( "Votar", Recursos.getRecursos("win.gif"), "Votar em Windows", aplicacaoWindows.getBmvcCommand()); BmvcButtonCTRL btMac = new BmvcButtonCTRL( "Votar", Recursos.getRecursos("mac.gif"), "Votar em Mac SO", aplicacaoMac.getBmvcCommand()); BmvcButtonCTRL btLinux = new BmvcButtonCTRL( "Votar", Recursos.getRecursos("linux.gif"), "Votar em Linux", aplicacaoLinux.getBmvcCommand() ); BmvcButtonCTRL btSair = new BmvcButtonCTRL( "Sair", Recursos.getRecursos("sair.gif"), "Sai da aplicação", aplicacaoSair.getBmvcCommand()); } } Classe - EnqueteResultadoView.java /* * EnqueteResultadoView - implementação da view */ package aplicacao.enquete.view; import java.util.*; import java.awt.*; import javax.swing.*; 56 import aplicacao.enquete.model.*; import framework.*; import framework.view.*; public class EnqueteResultadoView extends BmvcView { private JInternalFrame internalFrame; private EnqueteModel modelo; private JLabel[] labelValores; public JInternalFrame getInternalFrame() { return internalFrame; } public EnqueteResultadoView(int x, int y) { modelo = (EnqueteModel) BmvcAplic.getModel(); modelo.addView(this); internalFrame = new JInternalFrame("Enquete Resultado", false,true,false); internalFrame.getContentPane().setLayout(new GridLayout(3,2)); Iterator descricoes = modelo.getItens(); JLabel labelTexto; String texto; labelValores = new JLabel[modelo.getNDados()]; int valor; int i = 0; while(descricoes.hasNext()) { texto = descricoes.next().toString(); labelTexto = new JLabel(" " + texto); labelTexto.setForeground(Color.blue); internalFrame.getContentPane().add(labelTexto); labelValores[i] = new JLabel(); labelValores[i].setForeground(Color.red); internalFrame.getContentPane().add(labelValores[i++]); } internalFrame.setLocation(x,y); internalFrame.setSize(220, 140); internalFrame.setVisible(true); updateView(); } 57 public void updateView() { Iterator descricoes = modelo.getItens(); int valor; int i = 0; String sufixo; while(descricoes.hasNext()) { valor = modelo.getVotos(descricoes.next().toString()); if (valor>1) sufixo = "votos"; else sufixo = "voto"; labelValores[i++].setText(""+ valor+ " " +sufixo ); } } } Classe - EnqueteResultadoPorcView.java /* * EnqueteResultadoPorcView - implementação da view */ package aplicacao.enquete.view; import framework.view.BmvcView; import javax.swing.JInternalFrame; import aplicacao.enquete.model.EnqueteModel; import framework.BmvcAplic; import java.awt.GridLayout; import java.util.Iterator; import javax.swing.JLabel; import java.awt.Color; import java.text.DecimalFormat; public class EnqueteResultadoPorcView extends BmvcView { private JInternalFrame internalFrame; private EnqueteModel modelo; private JLabel[] labelValores; public JInternalFrame getInternalFrame() { return internalFrame; } public EnqueteResultadoPorcView(int x, int y) { 58 modelo = (EnqueteModel) BmvcAplic.getModel(); modelo.addView(this); internalFrame = new JInternalFrame("Enquete Resultado em %", false,true,false); internalFrame.getContentPane().setLayout(new GridLayout(modelo.getNDados(),2)); Iterator descricoes = modelo.getItens(); JLabel labelTexto; String texto; labelValores = new JLabel[modelo.getNDados()]; int valor; int i = 0; while(descricoes.hasNext()) { texto = descricoes.next().toString(); labelTexto = new JLabel(" " + texto); labelTexto.setForeground(Color.blue); internalFrame.getContentPane().add(labelTexto); labelValores[i] = new JLabel(); labelValores[i].setForeground(Color.red); internalFrame.getContentPane().add(labelValores[i++]); } internalFrame.setLocation(x,y); internalFrame.setSize(220, 140); internalFrame.setVisible(true); updateView(); } public void updateView() { Iterator descricoes = modelo.getItens(); Float valor; int i = 0; DecimalFormat formatador = new DecimalFormat(); formatador.applyPattern("0%"); while(descricoes.hasNext()) { valor = modelo.getVotosEmPorc(descricoes.next().toString()); labelValores[i++].setText(""+ formatador.format(valor)); } } } 59 Classe - EnqueteResultadoGraficoView.java /* * EnqueteResultadoGraficoView - implementação da view */ package aplicacao.enquete.view; import framework.view.BmvcView; import javax.swing.JInternalFrame; import aplicacao.enquete.model.EnqueteModel; import framework.BmvcAplic; import java.awt.GridLayout; import java.util.Iterator; import javax.swing.JLabel; import java.awt.Color; //biblioteca net.sourceforge.chart2d é software livre, tirada do site: www.sourceforge.net import aplicacao.enquete.recursos.net.sourceforge.chart2d.*; public class EnqueteResultadoGraficoView extends BmvcView { private JInternalFrame internalFrame; private EnqueteModel modelo; private Dataset dataset; private PieChart2D grafico2D; public JInternalFrame getInternalFrame() { return internalFrame; } public EnqueteResultadoGraficoView(int x, int y) { modelo = (EnqueteModel) BmvcAplic.getModel(); modelo.addView(this); internalFrame = new JInternalFrame("Enquete Resultado Gráfico", true, true, false); Object2DProperties object2DProps = new Object2DProperties(); object2DProps.setObjectTitleText("Enquete"); Chart2DProperties chart2DProps = new Chart2DProperties(); chart2DProps.setChartDataLabelsPrecision(0); 60 MultiColorsProperties multiColorsProps = new MultiColorsProperties(); PieChart2DProperties pieChart2DProps = new PieChart2DProperties(); //legendas LegendProperties legendProps = new LegendProperties(); Iterator descricoes = modelo.getItens(); String[] legendas = new String[modelo.getNDados()]; int i = 0; while (descricoes.hasNext()) legendas[i++] = descricoes.next().toString(); legendProps.setLegendLabelsTexts(legendas); //seta os dados int numCats = 1, numItems = 1; dataset = new Dataset(modelo.getNDados(), numCats, numItems); grafico2D = new PieChart2D(); grafico2D.setObject2DProperties(object2DProps); grafico2D.setChart2DProperties(chart2DProps); grafico2D.setLegendProperties(legendProps); grafico2D.setDataset(dataset); grafico2D.setMultiColorsProperties(multiColorsProps); grafico2D.setPieChart2DProperties(pieChart2DProps); internalFrame.getContentPane().add(grafico2D); internalFrame.setLocation(x, y); internalFrame.setSize(360, 300); internalFrame.setVisible(true); updateView(); } public void updateView() { Iterator descricoes = modelo.getItens(); int valor; int i = 0; String sufixo; while (descricoes.hasNext()) { valor = modelo.getVotos(descricoes.next().toString()); dataset.set(i++, 0, 0, valor); } grafico2D.repaint(); } } 61 Classe - Recursos.java package aplicacao.enquete.recursos; import java.net.URL; public class Recursos { public static URL getRecursos(String name) { return Recursos.class.getResource(name); } } Classe - SingletonPattern.java package padroes; final class Singleton { private static Singleton s = new Singleton(1); private int i; private Singleton(int x) { i = x; } public static Singleton getReference() { return s; } public int getValue() { return i; } public void setValue(int x) { i = x; } } public class SingletonPattern { public void testar() { Singleton s = Singleton.getReference(); System.out.println(s.getValue()); 62 s.setValue(2); System.out.println(s.getValue()); Singleton s2 = Singleton.getReference(); System.out.println(s.getValue()); } public static void main(String[] args) { SingletonPattern s = new SingletonPattern(); s.testar(); } } Classe - TemplateMethod.java package padroes; abstract class FrameworkTeste { public FrameworkTeste() { templateMethod(); } abstract void ajuste1(); abstract void ajuste2(); final void templateMethod() { for (int i = 0; i < 3; i++) { ajuste1(); ajuste2(); } } } // uma aplicação sob o FrameworkTeste class MinhaAplicacao extends FrameworkTeste { void ajuste1() { System.out.print("Olá "); } void ajuste2() { System.out.println("Mundo!"); } 63 } public class TemplateMethod { public static void main(String args[]) { new MinhaAplicacao(); } } Classe - CommandPattern.java package padroes; import java.util.*; interface Command { void execute(); } class Hello implements Command { public void execute() { System.out.print("Hello "); } } class World implements Command { public void execute() { System.out.print("World! "); } } // Guarda os comandos class Macro { private List commands = new ArrayList(); public void add(Command c) { commands.add(c); } public void run() { Iterator it = commands.iterator(); while (it.hasNext()) { ( (Command) it.next()).execute(); } 64 } } public class CommandPattern { public CommandPattern() { Macro macro = new Macro(); macro.add(new Hello()); macro.add(new World()); macro.run(); } public static void main(String args[]) { CommandPattern c = new CommandPattern(); } } 65