Baixe o app para aproveitar ainda mais
Prévia do material em texto
PADRÕES DE PROJETO DE SOFTWARE AULA 01 FUNDAMENTOS DE PADRÕES DE PROJETO Nesta aula, você irá: 1. Conhecer o conceito de padrão de projeto e a suas aplicações. 2. Entender a descrição de um padrão de projeto e como usar. 3. Conhecer as duas principais famílias de padrões de projeto que serão estudadas no decorrer da disciplina. 4. Iniciar o estudo dos padrões de projeto da família GoF. Introdução ✴ Projetar software OO reusável e de boa qualidade é uma tarefa difícil; ✴ Para realizar essa tarefa a contento, projetistas experientes usam soluções de sucesso com as quais já trabalharam no passado; ✴ Isso leva à descoberta de padrões de projeto; ✴ Durante duas décadas, a comunidade de padrões vem se desenvolvendo de acordo com essa dinâmica. PADRÕES DE PROJETO DE SOFTWARE 1 O que é um padrão? •Maneira testada ou documentada de alcançar um objetivo qualquer; • Padrões são comuns em várias áreas da engenharia; • Design Patterns, ou Padrões de Projeto; • Padrões para alcançar objetivos na engenharia de software usando classes e métodos em linguagens orientadas a objeto; •Inspirado em "A Pattern Language" de Christopher Alexander, sobre padrões de arquitetura de cidades, casas e prédios; • "Design Patterns" de Erich Gamma, John Vlissides, Ralph Jonhson e Richard Helm, conhecidos como "The Gang of Four", ou GoF, descreve 23 padrões de projeto úteis PADRÕES DE PROJETO DE SOFTWARE 2 Christopher Alexander Erich Gamma e outros. "Cada padrão descreve um problema que ocorre repetidas vezes em nosso ambiente, e então descreve o núcleo da solução para aquele problema, de tal maneira que pode-se usar essa solução milhões de vezes sem nunca fazê-la da mesma forma duas vezes" Christopher Alexander, sobre padrões em Arquitetura "Os padrões de projeto são descrições de objetos que se comunicam e classes que são customizadas para resolver um problema genérico de design em um contexto específico" Gamma, Helm, Vlissides & Johnson, sobre padrões em software “Um padrão é a abstração de uma forma concreta que ocorre muitas vezes em contextos específicos.” Riehle & Zullighoven, 1996 “Resolve um problema. É um conceito provado. A solução não é óbvia. Descreve um relacionamento.” Jim Coplien, 1996 PADRÕES DE PROJETO DE SOFTWARE 3 Padrões - características ✴ C a p t u r a m s o l u ç õ e s d e p r o j e t o exaustivamente refinadas com o passar do tempo; ✴ São o resultado de um longo processo de projeto, re-projeto, teste e reflexão sobre o que torna um sistema mais flexível, reusável e modular; Catálogos de padrões Um catálogo de padrões é um grupo de padrões que estão relacionados de uma certa forma e p o d e m s e r u s a d o s j u n t o s o u independentemente: • Core JEE(Java Enterprise Edition); • PoEAA(PatternsofEnterprise Application Architecture); • P O S A ( P a t t e r n - O r i e n t e d S o f t w a r e Architecture) • GRASP(General Responsibility Assignment Software Patterns/Principles) • GoF(Gang ofFour) PADRÕES DE PROJETO DE SOFTWARE 4 INTRODUÇÃO AOS PADRÕES DE PROJETO ★ANOS 70 Curiosamente, a ideia de padrões de projeto iniciou na área de arquitetura, através da publicação de dois livros (A Pattern Language e A Timeless Way of Building) pelo arquiteto Christopher Alexander no final dos anos 70. Alexander detectou problemas recorrentes em arquitetura e planejamento urbano e os capturou, descreveu e os formalizou em instruções que ele chamou de padrões. ★1987 As ideias de Alexander permaneceram esquecidas por um bom período, até que os p rogramadores Ken t Beck e Ward Cunningham propuseram os primeiros padrões de projeto para a área da Ciência da Computação em 1987. Porém, a área de padrões de projeto começou a ganhar força e notoriedade a partir da publicação do livro Design Patterns: Elements of Reusable Object-Oriented Software por Erich Gamma, PADRÕES DE PROJETO DE SOFTWARE 5 Richard Helm, Ralph Johnson e John Vlissides em 1985. Mais tardes estes autores ficaram conhecimento como a "Gangue dos Quatro" (Gang of Four) ou simplesmente GoF. ★2004 Outro marco importante na área de padrões de projeto foi a publicação do conjunto de padrões GRASP (General Responsibility Assignment Software Patterns) no livro Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development de Craig Larman em 2004. Os padrões de projeto GRASP podem ser considerados como um apoio para aplicar os conceitos de orientação a objetos de um modo metódico, racional e mais didático. PADRÕES DE PROJETO DE SOFTWARE 6 Catálogo - GoF PADRÕES DE PROJETO DE SOFTWARE 7 Por que aprender padrões? Aprender com a experiência dos outros • Ident ificar prob lemas comuns em engenharia de software e utilizar soluções testadas e bem documentadas; • Utilizar soluções que têm um nome: facilita a comunicação, compreensão e documentação; Aprender a programar bem com orientação a objetos • Os 23 padrões de projeto "clássicos" utilizam as melhores práticas em OO para atingir os resultados desejados; Desenvolver software de melhor qualidade • Os padrões utilizam eficientemente polimorfismo, herança, modularidade, composição, abstração para construir código reutilizável, eficiente, de alta coesão e baixo acoplamento; DESCRIÇÃO DE PADRÕES DE PROJETO Conforme descrito anteriormente, padrões de projeto são voltados para problemas recorrentes que ocorrem no nosso dia-a-dia, seja na área de desenvolvimento de software, seja em qualquer outra área do conhecimento. Formalmente, pode-se definir um padrão de projeto da seguinte maneira: PADRÕES DE PROJETO DE SOFTWARE 8 Cada padrão descreve um problema que ocorre repetidas vezes em nosso ambiente e fornece o núcleo da solução para aquele problema, de tal maneira que pode-se usar essa solução milhões de vezes sem nunca fazê-la da mesma forma duas vezes. Os padrões de projeto são descrições de objetos que se comunicam e classes que são customizadas para resolver um problema genérico de design em um contexto específico. Padrões de projeto Padrões de projeto estão relacionados a d i f e r e n t e s n í v e i s d e a b s t r a ç ã o n o desenvolvimento de aplicações orientadas a objetos, podendo aparecer ao longo de todo ciclo de análise e projeto de um sistema. Portanto a diversidade de padrões disponíveis é bastante grande, pode-se ter, por exemplo, padrões arquiteturais, padrões de análise, padrões de projeto e padrões de código. Esta disciplina está concentrada no uso de padrões de projeto direcionados para a etapa de implementação da aplicação. PADRÕES DE PROJETO DE SOFTWARE 9 Dessa forma, o aprendizado da área de padrões de projetotem se mostrado muito promissor, a aplicação dos seus conceitos já desponta em muitas linguagens de programação orientada a objetos. Além dos benefícios tradicionais relacionados com produtividade, redução do tempo de desenvolvimento e reaproveitamento de soluções passadas, a utilização de padrões de projeto pode contribuir ainda nos seguintes aspectos (Gamma et al., 2000): 1. É uma abordagem complementar, auxiliam os analistas e desenvolvedores a melhor utilizar as práticas tradicionais de análise e projeto orientado a objetos, tais como abstração, encapsulamento, herança, polimorfismo, entre outros. 2. Auxiliam programadores inexperientes a desenvolverem soluções mais elegantes, melhor documentadas, padronizadas e reutilizáveis. 3. Mu i t os dos pad rões de p ro j e t o desenvolvidos auxiliam no refatoramento da aplicação. 4. Auxilia na aprendizagem a partir da d o c u m e n t a ç ã o d e e x p e r i ê n c i a s passadas. PADRÕES DE PROJETO DE SOFTWARE 10 DOCUMENTAÇÃO Muitas destes benefícios são conseqüências da documentação gerada para cada tipo de padrão criado, Gamma et al. (2004) recomenda as seguintes informações básicas: NOME Apelido gerado para tratamento do problema abordado. O nome deve representar o conteúdo abordado, pois estabelece o primeiro nível do entendimento; PROBLEMA Descreve a situação em que se deve aplicar o padrão. Pode descrever um projeto específico, representar algoritmos como objetos, estruturas de classe ou objeto ou, ainda uma lista de condições que devem ser satisfeitas para que faça sentido aplicar o padrão; SOLUÇÃO Descreve os elementos que compõe o p a d r ã o , s e u s r e l a c i o n a m e n t o s , responsabilidades e colaborações. Fornece uma descrição abstrata de um problema de projeto e de como um arranjo geral de elementos o resolve; CONSEQUÊNCIAS Apresenta os resultados e as análises de vantagens e desvantagens da aplicação do PADRÕES DE PROJETO DE SOFTWARE 11 padrão. As conseqüências são importantes para avaliar alternativas de projeto e compreensão dos custos e benefícios da aplicação do padrão; PADRÕES RELACIONADOS Informar uma l istagem dos padrões relacionados ao estudo do problema e sua solução. PADRÕES GoF No decorrer desta disciplina estudaremos duas grandes famílias de padrões de projeto: GoF e GRASP. A partir da aula de hoje iniciaremos o estudo da família de padrões GoF, a qual está divida em três grupos principais de padrões: 1.Padrões de Criação: Fornecem um guia de como instanciar objetos. Esta ação normalmente envolve decisões dinâmicas para escolher, por exemplo, qual classe instanciar ou a quais objetos delegar responsabilidade. Esse padrão nos mostra como estruturar e encapsular essas decisões. Há cinco padrões de criação GoF: Abstract Factory, Builder, Factory Method, Prototype e Singleton. PADRÕES DE PROJETO DE SOFTWARE 12 2.Padrões Estruturais: Definem caminhos comuns para a organização de diferentes tipos de objetos, facilitando sua integração e colaboração mutua. Há sete padrões estruturais GoF: Adapter, Bridge, Composite, Decorator, Façade, Flyweight e Proxy 3.Padrões Comportamentais: São projetados para organizar, gerenciar e combinar diferentes comportamentos. Há 11 padrões comportamentais GoF: Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method e Visitor. Classificação dos padrões GoF segundo Metsker [2] PADRÕES DE PROJETO DE SOFTWARE 13 Resumo do padrões GoF 1. Adapter: Converter a interface de uma classe em outra interface esperada pelos clientes. 2. Façade: Oferecer uma interface única de nível mais elevado para um conjunto de interfaces de um subsistema. 3. Composite: Permitir o tratamento de objetos individuais e composições hierárquicas desses objetos de maneira uniforme. 4. Bridge: Desacoplar uma abstração de sua implementação, de tal forma que os dois possam variar independentemente. 5. Singleton: Garantir que uma classe só tenha uma única instância, e prover um ponto de acesso global a ela. 6. Observer: Definir uma dependência um- para-muitos entre objetos para que, quando um objeto mudar de estado, os seus dependentes sejam notificados e atualizados. 7. Mediator : Definir um objeto que encapsula a forma como um conjunto de objetos interage. PADRÕES DE PROJETO DE SOFTWARE 14 8. Proxy: Prover um substituto ou ponto através do qual um objeto possa controlar o acesso a outro. 9. Chain of Responsibility: Compor objetos em cascata para, através dela, delegar uma requisição até que um objeto a sirva. 10. Flyweight: Usar compartilhamento para supor tar efic ientemente grandes quantidades de objetos complexos. 11. Builder: Separar a construção de objeto complexo da representação para criar representações diferentes com mesmo processo. 12. FactoryMethod: Definir uma interface para criar um objeto mas deixar que subc lasses dec idam que c lasse instanciar. 13. Abstract Factory: Prover interface para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas. 14. Prototype: Especificar tipos a criar usando uma instância como protótipo e criar novos objetos ao copiar este protótipo. PADRÕES DE PROJETO DE SOFTWARE 15 15. Memento: Externalizar o estado interno de um objeto para que o objeto possa ter esse estado restaurado posteriormente. 16. TemplateMethod: Definir o esqueleto de um algoritmo dentro de uma operação, deixando alguns passos a serem preenchidos pelas subclasses. 17. State: Permitir a um objeto alterar o seu comportamento quando o seu estado interno mudar. 18. Strategy: Definir uma famíl ia de algoritmos, encapsular cada um, e fazê- los intercambiáveis. 19. Command: Encapsular uma requisição como objeto, para parametrizar clientes com diferentes requisições, filas e dar suporte a ações reversíveis. 20. Interpreter: Dada uma linguagem, definir uma representação para sua gramática junto com um interpretador. 21. Decorator: Anexar responsabilidades adicionais a um objeto dinamicamente 22. Iterator: Prover acesso sequencial a elementos de um objeto agregado, sem expor sua representação interna 23. Visitor: Representar uma operação a ser realizada sobre os elementos de uma estrutura de objetos PADRÕES DE PROJETO DE SOFTWARE 16 Classificação dos 23 padrões segundo GoF* FactoryMethod "Definir uma interface para criar um objeto mas deixar que subclasses decidam que classe instanciar. Factory Method permite que uma classe delegue a responsabilidade de instanciamento às subclasses." [GoF] O padrão FactoryMethod é caracterizado por retornar uma instância de uma classe, de acordo com parâmetros informados para o método, dessa forma, ao invés do c l iente (ou programador) instanciar classes utilizando o operador new, ele chama um método genérico PADRÕES DE PROJETO DE SOFTWARE17 de criação apropriado. Por exemplo, considere uma superclasse Carro com quatro classes derivadas: Vectra, Omega, Gol e Golf. Suponha agora que é necessário instanciar objetos da classe Carro em um método pertencente a classe Montadora. A sequência de comandos a seguir apresenta uma solução comumente aceita e praticada por inúmeros desenvolvedores. public class Montadora { public void novoCarro(String tipo) { Carro carroZero; if(tipo.equals(“Vectra”)) carroZero = new Vectra(); else if(tipo.equals(“Omega”)) carroZero = new Omega(); else if(tipo.equals(“Gol”)) carroZero = new Gol(); else if(tipo.equals(“Golf”)) carroZero = new Golf(); } }; PADRÕES DE PROJETO DE SOFTWARE 18 FactoryMethod PADRÕES DE PROJETO DE SOFTWARE 19 A partir do diagrama apresentado na Figura 1, pode-se fazer as seguintes analogias com a estrutura do padrão apresentado por Gamma et al. (2000): ★ A classe carro é uma classe abstrata (product) que define a interface dos objetos que o método fábrica cria; PADRÕES DE PROJETO DE SOFTWARE 20 ★ A classe montadora é a classe client, que vai solicitar instancias de carros à classe carfactory; ★ A s c l a s s e s d e r i v a d a s d e c a r r o , correspondem a concreteproduct; ★ A classe carfactory corresponde a classe concretecreator. Como implementar? • É possível criar um objeto sem ter conhecimento algum de sua classe concreta? ✓ Esse conhecimento deve estar em alguma parte do sistema, mas não precisa estar no cliente ✓ FactoryMethod define uma interface comum para criar objetos ✓ O objeto específico é determinado nas diferentes implementações dessa interface ✓ O cliente do FactoryMethod precisa saber sobre implementações concretas do objeto criador do produto desejado PADRÕES DE PROJETO DE SOFTWARE 21 Como selecionar o criador? • Para criar objetos não é mais preciso saber a classe concreta do objeto a ser criado, mas ainda é preciso saber a classe do criador. • Para escolher qual criador usar sem que seja preciso instanciá-lo com um construtor, crie uma classe Factory com um método estático que decida qual criador usar com base em um parâmetro PADRÕES DE PROJETO DE SOFTWARE 22 Prós e contras • Vantagens • Criação de objetos é desacoplada do conhecimento do tipo concreto do objeto • Conecta hierarquias de classe paralelas • Facilita a extensibilidade • Desvantagens • Ainda é preciso saber a classe concreta do criador de instâncias (pode-se usar uma classe Factory, com método estático e parametrizado que chame diretamente o Factory Method): PADRÕES DE PROJETO DE SOFTWARE 23 Abstract Factory "Prover uma interface para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas." [GoF] Estrutura de Abstract Factory O padrão Abstract Factory apresenta um nível de abstração superior quando comparado ao padrão FactoryMethod. Apresenta como uma de suas vantagens controlar as classes de objetos PADRÕES DE PROJETO DE SOFTWARE 24 criados por uma aplicação, restringindo o acesso as classes concretas e isolando os clientes das classes de implantação Além disso, como as fábricas abstratas aparecem uma vez na aplicação, no momento de sua instanciação, tem-se facilidade para utilizar diferentes configurações, simplesmente localizando e trocando a fábrica abstrata por outra. O primeiro grupo, formado pela classe carro e suas classes derivadas, representa os diferentes produtos a serem criados pelas fábricas concretas, não há informações para diferenciar os produtos conforme seu fabricante, esta diferenciação é feita pelas fábricas. O segundo grupo formado pelas classes Montadoras e suas classes der ivadas, implementando a interface e as operações que PADRÕES DE PROJETO DE SOFTWARE 25 criam os produtos concretos, associados a cada tipo de fábrica. Para utilizar instanciar um determinado carro, instancia-se primeiro o fabricante e a seguir o modelo de carro desejado. A imagem apresenta o diagrama UML com um exemplo de utilização do padrão AbstractFactory na implementação de um conjunto de classes para instanciar carros de acordo com seu respectivo fabricante, semelhante ao exemplo anterior, sobre FactoryMethod. Porém, diferente do anterior, a implementação prevê dois grupos de classes de carros: Volkswagem e General Motors, conforme a estrutura do padrão presentes no diagrama. Fazendo analogia com a estrutura do padrão AbstractFactory apresentado em Gamma et al (2000), tem-se as seguintes correspondências: ★ A classe montadora corresponde a abstractfactory; ★ A c l a s s e c a r r o c o r r e s p o n d e a abstractproducta; ★ A classe Gol corresponde a Product A3. ★ A classe Golf corresponde a Product A4. PADRÕES DE PROJETO DE SOFTWARE 26 ★ A s c l a s s e v o l k s c o r r e s p o n d e a concretefactory1; ★ A classe Omega corresponde a Product A1. ★ A c l a s s e G M c o r r e s p o n d e a concretefactory2; Nesta aula, você: •Estudou a origem e as principais motivações para aplicar padrões de projeto em projetos de desenvolvimento de software. •Identificou as duas grandes famílias de padrões de projeto mais comumente utilizadas: gof e GRASP. •Estudou dois exemplos com aplicações práticas sobre os padrões de criação FactoryMethod e AbstractFactory. REGISTRO DE PARTICIPAÇÃO 1. Assinale a alternativa que apresenta apenas padrões de criação GoF. 1) AbstractFactory, FactoryMethod, Builder. 2) AbstractFactory, FactoryMethod, Adapter. 3) Adapter, FactoryMethod, Builder. PADRÕES DE PROJETO DE SOFTWARE 27 4) Interpreter, Singleton, FactoryMethod. 5) Builder, Singleton, FactoryMethod. 2.Qual padrão de projeto permite a criação de objetos através de um método genérico, sem que o cliente precise ter conhecimento de qual classe concreta está sendo usada? 1) AbstractFactory. 2) Builder. 3) Template Method. 4) Singleton. 5) Mediator. 3. Qual padrão de projeto permite a criação de uma família de objetos relacionados ou dependentes sem especificar a classe concreta que será utilizada? 1) Mediator. 2) Builder. 3) Template Method. 4) Singleton. 5) AbstractFactory. PADRÕES DE PROJETO DE SOFTWARE 28 CCT0152_EX_A1_201102276103 Disciplina: CCT0152 - PAD.PROJ.SOFTWARE Período Acad.: 2014.1 - EAD (G) / EX 1. Relacione os padrões de projetos listados abaixo com suas respectivas finalidades: PADRÕES DE PROJETO 1. Facade (fachada) 2. Decorator (decorador) 3. Memento (lembrança) 4. Proxy (procurador) 5. Observer (observador)FINALIDADES ( ) Define uma dependência um para muitos entre objetos tal que, quando o estado de um objeto muda, todos os seus dependentes são notificados e atualizados automaticamente. ( ) Fornece uma interface unificada para um conjunto de objetos que constituem um subsistema. Define uma interface de mais alto nível que torna o subsistema mais fácil de usar. ( ) Sem violar o encapsulamento, captura e exterioriza o estado interno de um objeto, tal que o objeto possa ser restaurado a este estado mais tarde. ( ) Acrescenta responsabilidades adicionais a um objeto dinamicamente. Fornece uma alternativa PADRÕES DE PROJETO DE SOFTWARE 29 flexível para a extensão de funcionalidade. ( ) Controla o acesso a um objeto através de outro objeto, que atua como seu substituto, ou como um envoltório. Assinale a alternativa que indica a sequência correta, de cima para baixo. ( X ) 5 - 1 - 3 - 2 - 4 ( ) 1 - 5 - 3 - 4 - 2 ( ) 5 - 1 - 3 - 4 - 2 ( ) 3 - 1 - 5 - 2 - 4 ( ) 3 - 5 - 1 - 4 - 2 2. A família de padrões GoF é dividida em três grupos principais de padrões, a saber: ( ) Padrões de Processo; Padrões de Singularidade; Padrões de Prototipação ( ) Padrões Estruturais; Padrões de Processo; Padrões de Responsabilidade ( X ) Padrões Comportamentais; Padrões de Criação; Padrões Estruturais ( ) Padrões de Proxy; Padrões de Criação; Padrões de Encadeamento ( ) Padrões de Criação; Padrões Metodológicos; Padrões de Ponte PADRÕES DE PROJETO DE SOFTWARE 30 3. Os design patterns ( ) são de uso exclusivo em processos de desenvolvimento de soluções orientado a objetos, já que os objetos são a mais adequada abstração para o reúso. ( ) consistem em conjuntos de classes que um usuário instancia para utilizar seus métodos. Após a chamada ao método, o controle do fluxo da aplicação retorna para o usuário. ( X ) podem ser modelados utilizando-se a linguagem UML que fornece um meio eficiente de modelar pa- drões de projeto representando-os como colaborações. ( ) são projetos de arquitetura para um domínio específico de aplicação e sempre trazem componentes predefinidos que envolvem código de programação. ( ) são aplicações propriamente ditas, normalmente construídas pela integração de diversos frameworks. PADRÕES DE PROJETO DE SOFTWARE 31 AULA 02 PADRÕES DE CRIAÇÃO GOF Nesta aula, você irá: 1.Conhecer os padrões de criação Builder, Prototype e Singleton. 2.Aprender as pr inc ipa is ap l icações e funcionalides destes padrões. BUILDER O padrão de projeto Builder é utilizado na instanciação de objetos complexos. Portanto, in ic ia lmente, é preciso entender como caracterizar um objeto complexo. Um objeto é caracterizado como complexo quando ele é associado a outros objetos por qualquer tipo de relacionamento conhecido ou ainda quando ele apresenta atributos que são instanciados a partir de diferentes regras de negócio. Nestas circunstâncias, instanciar objetos não é trivial, diferentes condições e situações devem ser consideradas. O padrão Builder é bastante utilizado nestas situações, podendo ser visto como um construtor especializado, que irá executar e avaliar diferentes regras de negócio e demais particularidades relacionadas com a criação de PADRÕES DE PROJETO DE SOFTWARE 32 um novo ob je to . A ide ia é a t r ibu i r a responsabilidade de criação do objeto complexo a outra classe, esta classe irá armazenar todas as configurações e regras necessárias para a instanciação do novo objeto. Uma solução natural, apresentada por muitos desenvolvedores, é embutir no construtor da própria classe a lógica para criação de um objeto ou ainda distribuir a lógica de criação em vários métodos adicionais. Um dos principais objetivos do padrão Builder é evitar este tipo de estratégia, seu propósito é separar o algoritmo de criação de um objeto complexo tanto da especificação, quanto das partes que o compõem. Esta abordagem facilita a criação de objetos com diferentes configurações e representações, facilita a manutenção do código, reduz a complexidade das classes relacionadas (a complexidade de criação é atribuída ao Builder) e melhora a legibilidade da solução final, ou seja, para entender como um objeto é criado e sob quais condições, deve-se avaliar a classe Builder responsável por esta ação. EXEMPLIFICANDO BUILDER Como um exemplo, vamos considerar a necessidade de instanciar um objeto da uma PADRÕES DE PROJETO DE SOFTWARE 33 classe Pedido, a qual é formada por um conjunto de itens de pedido (Produtos) e por outros atributos específicos, tais como numero, data e vendedor. A imagem apresenta o diagrama de classes em UML com a solução proposta utilizando o padrão Builder. Inicialmente, foram projetadas as três classes básicas relacionadas com o problema: Produto, Pedido e Vendedor. Após, foi projetada a classe PedidoBuilder para realizar a instanciação de objetos Pedido. Para efeito de simplificação da interface da classe PedidoBuilder, todos os parâmetros necessários para instanciar uma classe Pedido foram agrupados no atributo parâmetros do tipo String. PADRÕES DE PROJETO DE SOFTWARE 34 PADRÕES DE PROJETO DE SOFTWARE 35 De acordo com a estrutura proposta, o método buildPedido é responsável por chamar cada método da classe Pedido e assim gerar um objeto completo, enquanto que o método getPedido retorna o objeto Pedido construído pelo método buildPedido. Observe que o método buildPedido realiza todas as chamadas necessárias para a criação completa de uma instância do objeto Pedido. Se por ventura, futuramente, a classe Pedido sofrer a lguma a l te ração , somente o método buildPedido da classe PedidoBuilder deverá ser alterado. A seqüência de comandos abaixo ilustra como é a criação de um objeto Pedido usando a classe pedidoBuilder. PADRÕES DE PROJETO DE SOFTWARE 36 … String configuracao; // informar todos os dados necessários PedidoBuilder builder; Pedido pedido; builder = new pedidoBuilder(configuracao); builder.buildPedido(); pedido = builder.getPedido(); // Listar atributos System.out.println(pedido.getNumero); … Comparando o diagrama de classe apresentado na imagem com a estrutura do padrão de projeto Builder proposta em Gamma et al. (2000), tem- se que a classe PedidoBuilder corresponde a ConcreteBuilder, Pedido corresponde a Product e Director será qualquer classe que utilizará o padrão Builder para instanciar objetos Pedido. A classe Builder especifica uma interface abstrata, definindo as operações básicas que devem ser implementadas pelas classes derivadas. Por fim, é importante destacar a diferença entre o padrão AbstractFactory, estudado na aula anterior, e o padrão Builder, pois ambos estão direcionados a criação de objetos. A principal diferença entre eles é que o Builder constrói PADRÕES DE PROJETO DE SOFTWARE37 objetos complexos passo-a-passo, retira-se o algoritmo de criação do construtor da classe do objeto e criar-se uma nova classe com esta responsabilidade, enquanto que AbstractFactory constrói famílias de objetos relacionados, simples ou complexos, de uma só vez, primeiro instancia-se a família do objeto e a seguir o objeto propriamente dito. Prototype O padrão de projeto Prototype declara um método chamado clone na superclasse abstrata do modelo (Prototype). Em função desta declaração, cada classe concreta derivada deve ser capaz de gerar uma nova instância de si próprio, ou seja, um método especializado capaz de construir objetos iguais a si mesmo, também podendo ser chamado de clone. Entre as aplicações para este padrão de projeto estão a facilidade de instanciar classes em tempo de execução. Quando as instancias de uma classe apresentam poucas combinações de estados, pode ser mais conveniente definir previamente um conjunto de protótipos e cloná- los, sempre que foi necessário. Além disso, é bastante útil para guardar o estado de um objeto PADRÕES DE PROJETO DE SOFTWARE 38 em determinados momentos, nesses casos, basta pedir uma cópia do próprio objeto, ao invés de criar uma nova instancia manualmente. EXEMPLIFICANDO Prototype A imagem ilustra um exemplo de aplicação do padrão Prototype. A classe CarroClone é uma interface que declara o método clone, a ser implementado nas classes derivadas. Desse modo, a classe Carro implementa este método retornando uma nova instancia da classe a partir dos valores atuais dos seus atributos. A implementação deste padrão de projeto é facilitada na linguagem de programação Java com a utilização da interface Cloneable, utilizada apenas para indicar que o método Object.clone() pode realizar uma cópia, atributo por atributo, das instâncias da classe. PADRÕES DE PROJETO DE SOFTWARE 39 PADRÕES DE PROJETO DE SOFTWARE 40 Singleton O padrão de projeto Singleton é um dos padrões mais conhecidos e extensivamente utilizados em programação orientada a objetos. Está direcionado para as situações onde precisamos manter uma única instancia de uma classe durante toda a execução da aplicação. Por exemplo, para garantir apenas um spooler de impressão, embora tenhamos d iversas impressoras em um sistema, para armazenar uma conexão com uma base de dados que será chamadas diversas vezes, para armazenar o log da execução de uma aplicação, para centralizar os dados de configuração de um sistema, para armazenar os dados do usuário que está logado em um sistema, entre outros. A sua estrutura é bastante simples, existe apenas uma classe chamada Singleton, que define um método chamado Ins tance , responsável poder retornar aos clientes a única instancia da classe. Alguns recursos das linguagens de programação orientadas a objeto devem ser utilizados para garantir a correta implementação desta classe, por exemplo, em linguagem Java, podemos utilizar os seguintes recursos: PADRÕES DE PROJETO DE SOFTWARE 41 1.Modificadores static e private para garantir uma mesma instância para todos os objetos criados e evitar acesso público; 2.Modificar static para implementar o método getInstance e, assim, retornar a instancia apropriada ou criá-la, caso seja a primeira vez; 3.Construtor da classe privado, para não permitir a instância de novos objetos da classe; 4.Declarar o método getInstance como synchronized para que o método seja executado por uma thread por vez, quando utilizado em programas multi-thread; O código Java apresentado, mostra um esqueleto básico para implementação do padrão Singleton. Pesquise por exemplos e faça testes de instanciação e uso em seu ambiente de programação Java favorito. public class Singleton { private static Singleton instance; // Adicione aqui classes aninhadas ou atributos private private Singleton() { } PADRÕES DE PROJETO DE SOFTWARE 42 public static synchronized Singleton getInstance() { if (instance == null) instance = new Singleton(); return instance; } // implemente os demais métodos necessários (get e set) } 1 Nesta aula, você: Estudou três padrões de criação: builder, singleton e prototype. Identificou as situações onde cada um deles deve ser aplicado. Estudou três exemplos práticos com a utilização destes padrões. REGISTRO DE PARTICIPAÇÃO 1. Assinale a alternativa que apresenta a situação que melhor caracteriza a utilização do padrão de projeto Singleton. PADRÕES DE PROJETO DE SOFTWARE 43 (1) Uma classe cliente pode acessar uma classe do sistema através de uma interface diferente da classe desejada. (2) Uma classe cliente precisa de uma interface idêntica à da classe existente, mas não tem acesso direto a ela. (3) Uma classe cliente precisa acessar um método que simplifique o acesso a uma hierarquia de classes. (4) Uma classe cliente precisa de uma classe que retorne uma única instância de uma classe existente. (5) Uma classe cliente precisa ser notificada sobre alterações no estado de um objeto. 2. O objetivo do padrão de projeto Builder é: (1) especificar os tipos de objetos a serem criados, usando uma instância-protótipo. (2) acessar uma classe do sistema através de uma interface diferente da classe desejada. (3) i m p l e m e n t a r u m a l g o r i t m o p a r a instanciar um objeto complexo. (4) retornar a única instância de uma classe. (5) retornar o clone de um objeto. PADRÕES DE PROJETO DE SOFTWARE 44 3 . Q u a l p a d r ã o d e p r o j e t o t e m s u a implementação facilitada pelo uso da interface Cloneable da linguagem de programação Java? 1) Prototype. 2) Builde. 3) Singleton. 4) FactoryMethod. 5) AbstractFactory. PADRÕES DE PROJETO DE SOFTWARE Exercício: CCT0152_EX_A2_201102276103 1a Questão (Ref.: 201102411490) Considerando a classe de projetos GoF assinale a opção cujos padrões de projeto estão todos classificados como criação: ( ) Abstractly factory ; Bridge ; Factory Method ; Protype ; Singleton ( X ) Abstractly factory ; Builder ; Factory Method ; Protype - Singleton ( ) Abstractly factory ; Builder ; Composite ; Protype - Singleton ( ) Command ; Builder ; Factory Method ; Protype - Singleton ( ) Abstractly factory ; Builder ; Factory Method ; Decorator - Singleton PADRÕES DE PROJETO DE SOFTWARE 45 2a Questão (Ref.: 201102411493) Considerando a classe de projetos GoF assinale a opção cujos padrões de projeto estão todos classificados como Estruturais: ( ) adapter ; bridge ; protype ¿ decorator ; faça de ; flyweight ; singleton ( X ) adapter ; bridge ; composite ; decorator ; faça de ; flyweight ; Proxy ( ) singleton; bridge ; protype; decorator ; faça de ; flyweight ; Proxy ( ) adapter ; bridge ; composite ; decorator ; faça de ; flyweight ; singleton ( ) singleton; bridge ; composite; decorator ; faça de ; flyweight;¿Proxy 3a Questão (Ref.: 201102411499) Consideram as afirmativa abaixo sobre o padrão protype I. Declara um método chamado clone na superclasse abstrata do modelo (Prototype). Em função desta declaração, cada classe concreta derivada deve ser capaz de gerar uma nova instância de si próprio. II. Entre as aplicações para este padrão de projeto está a facilidade de instanciar classes em tempo de execução. III. Quando as instancias de uma classe apresentam poucas combinações de PADRÕES DE PROJETO DE SOFTWARE 46 estados, pode ser mais conveniente definir previamente um conjunto de protótipos e cloná-los, sempre que foi necessário. ( X ) As afirmativas estão todas corretas ( ) As afirmativas II, III estão corretas e a afirmativa I está errada. ( ) As afirmativas I, III, estão corretas e II errada ( ) As afirmativas I, II, III estão incorretas ( ) As afirmativas I, II, estão corretas e a afirmativa III está errada. PADRÕES DE PROJETO DE SOFTWARE 47 AULA 03: PADRÕES ESTRUTURAIS GOF (I) Nesta aula, você irá: 1.Aprender as principais características dos padrões estruturais. 2.Conhecer os padrões de estruturais Adapter, Bridge, Composite e Decorate. 3.Aprender as pr inc ipa is ap l icações e funcionalidades destes padrões. Decorator Programadores se deparam muitas vezes com a s i t uação onde é p rec i so ac rescen ta r responsabilidades a objetos e não a classe. Uma das opções é utilizar herança, entretanto, esta alternativa é estática. Outra alternativa é especificar uma nova classe para implementar cada responsabilidade que se deseja atribuir dinamicamente a um dado objeto. Esta nova classe se chama Decorator. Exemplificando Decorator No exemplo apresentado na imagem utiliza-se como exemplo a montagem uma massa em um sistema de fast food. Inicialmente, escolhe-se o tipo da massa e a seguir escolhem-se os acompanhamentos (Decorator). Nesse caso, a PADRÕES DE PROJETO DE SOFTWARE 48 implementação utilizando herança seria bastante complexa, i r ia requerer uma sér ie de combinações diferentes. Na modelagem apresentada, primeiro escolhe-se o tipo de massa e a segu i r acrescentam-se os acompanhamentos, cada qual, será adicionado dinamicamente ao objeto massa que foi previamente criado. PADRÕES DE PROJETO DE SOFTWARE 49 PADRÕES DE PROJETO DE SOFTWARE 50 No exemplo apresentado, há quatro tipos de massas derivadas da classe abstrata Massa: Ravioli, Canelone, Spaghetti e Penne. Além de uma classe abstrata CondimentosDecorator que possui cinco classes derivadas: Molho4Queijos, MolhoSugo, MolhoBranco, Carne e Vegetais. Cada uma destas classes apresenta um método PADRÕES DE PROJETO DE SOFTWARE 51 construtor que recebe os seguintes parâmetros: massa, descrição e custo do acompanhamento. Assim, uma vez instanciado um objeto Massa, pode-se adicionar dinamicamente diferentes condimentos. O trecho de código Java a seguir ilustra o funcionamento do método construtor d a s c l a s s e s d e r i v a d a s d e CondimentosDecorator, fundamental para entender o funcionamento do padrão. … public Carne(Massa pmia, double pcusto) { mia = pmia; nome = pmia.getNome() + " Carne "; custo= pmia.custo() + pcusto; } … ATENÇÃO O decorador deve conhecer o objeto decorado. Veja que os valores originais dos atributos nome e custo do objeto Massa são somados a valores específicos para gerar o valor correspondente do objeto Carne, esta funcionalidade do método é que habi l i ta a a t r ibu ição d inâmica de PADRÕES DE PROJETO DE SOFTWARE 52 responsabilidades, cada novo objeto decorador recebe os valores anteriores e adiciona os seus próprios. O trecho de código abaixo apresenta a instanciação de um objeto massa e a adição de diferentes condimentos. … Massa miaMassa = new Ravioli("Ravioli del chef ", 16.0); miaMassa = new QuatroQueijos(miaMassa, 1.0); miaMassa = new Carne(miaMassa, 5.0); miaMassa = new Vegetais (miaMassa, 2.0); S y s t e m . o u t . p r i n t l n ( " N o m e = " + miaMassa.getNome() + " Preço da minha massa = " + miaMassa.custo()); … A saída gerada pelo programa será: Nome = Ravioli del chef QuatroQueijos Carne Vegetais Preço da minha massa = 24.0 PADRÕES DE PROJETO DE SOFTWARE 53 COMPOSITE O padrão de projeto Composite é utilizado, portanto, quando se pretende representar hierarquias partes-todo (ou todo-parte) de objetos, ou ainda, quando se pretende modelar relacionamento de agregação. A vantagem de utilizar este padrão é que o cliente irá acessar objetos compostos ou não de maneira uniforme, pois irá se relacionar com a classe abstrata Component. Ver, por exemplo, o método print do exemplo apresentado na Figura 2, quando se trata de uma parte, o processamento é realizado diretamente pela superclasse Componente, quando se trata de uma composição, o processamento é feito pela classe Composite, imprimindo todas as partes que compõem o objeto. PADRÕES DE PROJETO DE SOFTWARE 54 PADRÕES DE PROJETO DE SOFTWARE 55 A imagem apresenta um exemplo bem conhecido para destacar a utilização do padrão Composite. Inicialmente, foi modelado uma c lasse abst ra ta para representa cada componente (Componente), a seguir definiu-se os objetos folhas (Leaf), tais como HD, Teclado, Monitor, Impressora, Memória e PlacaMae e um o b j e t o c o m p o s t o ( C o m p o s i t e ) . N a implementação do ultimo, utilizou-se uma estrutura de dados auxiliar (Vector) para armazenar os objetos partes. O trecho de código abaixo ilustra a utilização do padrão Composite. PADRÕES DE PROJETO DE SOFTWARE 56 ADAPTER O padrão Adapter é bastante utilizado para compatibilizar classes implementadas por programadores diferentes, ou desenvolvidas em momentos diferentes, ou ainda para unir classes com interfaces diferentes em uma estrututura hierárquica única, sem precisar implementar novamente todas as funcionalidades e interfaces da classe já existente. A ideia é criar uma nova classe (Adapter) com a interface padrão que se deseja para fazer a conexão com a classe já existente (Adaptee) com interface diferente da estrutura de classes que se pretende utilizar no sistema. ✴ A imagem apresenta o exemplo de uma hierarquia de classes para implementar diferentes primitivas gráficas, o diagrama de classes parece estranho, mas há uma justificativa. Suponha que, desconhecendo o repositório de classes da empresa, um programador novato projetou a estrutura de classes conforme apresentado. ✴ Em primeiro lugar, definiu uma classe abstrata PrimitivaGrafica (Target, interface utilizada pelo cliente) e a seguir definiutrês PADRÕES DE PROJETO DE SOFTWARE 57 c lasses der ivadas (Ponto , L inha e Quadrado). ✴ Porém, graças a um colega de trabalho bastante compromet ido e atento, o programador novato descobriu que já existia uma classe chamada QuadradoAntiga (Adaptee) com todas as funcionalidades que ele desejava, porém com métodos e parâmetros diferentes do seu projeto. ✴ Para demonstrar sapiência no assunto e agilizar sua implementação, o programador novato resolveu importar a classe antiga no seu sistema, tal como ela havia sido desenvolvida originalmente e adaptar a sua classe Quadrado (Adapter) para fazer uso da classe antiga. ✴ Além de reaproveitar totalmente a classe antiga sem precisar alterar o código e entender a complexa implementação realizada, demonstrou aos seus colegas a importância do estudo de padrões de projeto para manter a uniformidade do seu projeto original. PADRÕES DE PROJETO DE SOFTWARE 58 PADRÕES DE PROJETO DE SOFTWARE 59 BRIDGE Desenvolver aplicações portáveis é um desejo de todo programador, permitir que o sistema consiga se adaptar dinamicamente a diferentes plataformas é mais desejável ainda. O padrão Bridge tem potencial para auxiliar nessas situações. A solução natural quando se pretende desenvolver uma determinada solução para duas plataformas diferentes é utilizar herança, implementando uma classe derivada para cada situação. No entanto, assim como discutido na PADRÕES DE PROJETO DE SOFTWARE 60 seção sobre o padrão Decorator, esta abordagem relaciona uma abstração (entende- se definição dos métodos e atributos) a sua implementação permanentemente, oferecendo pouca flexibilidade para mudanças e reutilização da das abstrações e implementações de forma independente. A imagem apresenta um exemplo que demonstra como tratar este tipo de situação utilizando o padrão Bridge. Inicialmente, definiu-se a classe abstrata Formas (Abstration) e três classe concretas derivadas (Ponto, Linha e Circulo) para especificar a interface da abstração (refindedAbstraction), com uma referência para a classe que vai implementar cada uma das abstrações definidas. Neste caso, a classe abstrata implementador (Implementor) chama-se DesenharAPI, esta classe possui duas classes d e r i v a d a s ( C o n c r e t e I m p l e m e n t o r A e ConcreteImplementorB), uma para cada tipo de sistema operacional (WindowsAPI e LinuxAPI). PADRÕES DE PROJETO DE SOFTWARE 61 PADRÕES DE PROJETO DE SOFTWARE 62 D e s s e m o d o , c o n s e g u e - s e s e p a r a r completamente a interface da classe da sua implementação, de tal modo que uma dada implementação pode ser definida em tempo de execução, até mesmo mudar de implementação em tempo de execução. O relacionamento entre as classes Formas e DesenharAPI leva o nome de Bridge (ponte) para fazer referencia ao nome do padrão de projeto utilizado. No trecho que código abaixo, demostra-se como instanciar a classe de implementação e a seguir como utilizá- la para desenhar um Circulo. … PADRÕES DE PROJETO DE SOFTWARE 63 DesenharAPI API = new WindowsAPI(); Circulo circulo = new Circulo(10, 20, 10, API); … Nesta aula, você: • Estudou quatro padrões estruturais: adapter, bridge, composite e decorator. • Identificou as situações onde cada um deles deve ser aplicado. • Estudou quatro exemplos práticos com a utilização destes padrões. REGISTRO DE PARTICIPAÇÃO 1. Qual o nome do padrão de projeto que pode ser utilizado para permitir que uma hierarquia de abstrações e suas diferentes implementações possam variar independentemente? 1) Adapter. 2) Proxy 3) Façade 4) Bridge 5) Flyweight PADRÕES DE PROJETO DE SOFTWARE 64 2. Marque a alternativa que melhor descreve uma situação típica onde poderia ser utilizado o padrão de projeto Adapter? 1) Um programador precisar utilizar uma classe que possui interface diferente da classe existente na aplicação. 2) Um programador precisa utilizar uma classe que possui a mesma interface da classe existente na aplicação. 3) Um programador precisa de um método que simplifique o acesso a uma hierarquia de classes. 4) Um programador precisa de uma classe que possua um método para retornar a única instância existente da classe. 5) Um programador precisa ser avisado quando houver alterações no estado de um objeto. 3. Um compositor musical deseja criar uma hierarquia de classes para representar a estrutura das suas notas musicais. Em primeiro lugar, definiu uma classe abstrata chamada Melodia, a seguir, criou duas classes derivadas, uma chamada Nota e outra chamada Partitura. Cada Nota musical representa o elemento mínimo de uma Melodia e cada Partitura é formada por uma ou mais notas. Marque a PADRÕES DE PROJETO DE SOFTWARE 65 alternativa que representa o melhor padrão de projeto para modelar este problema. 1) Adapter 2) Proxy 3) Façade 4) Bridge 5) Composite 4. Assinale a alternativa correspondente ao padrão de projeto utilizado para adicionar responsabilidades dinâmicas a objetos. 1) Adapter 2) Decorator 3) Façade 4) Bridge 5) Composite PADRÕES DE PROJETO DE SOFTWARE Exercício: CCT0152_EX_A3_201102276103 1a Questão (Ref.: 201102411501) O padrão de projeto Singleton é um dos padrões mais conhecidos e extensivamente utilizados em programação orientada a objetos. Sobre ele podemos afirmar PADRÕES DE PROJETO DE SOFTWARE 66 I. Está direcionado para as situações onde precisamos manter uma única instancia de uma classe durante toda a execução da aplicação. II. A sua estrutura é bastante simples, existe apenas uma classe chamada Singleton, que define um método chamado Instance, responsável poder retornar aos clientes à única instancia da classe. III. Na linguagem Java os modificadores states e private devem garantir uma mesma instância para todos os objetos criados e evitar acesso público; ( X ) As afirmativas estão todas corretas ( ) As afirmativas I, II, estão corretas e a afirmativa III está errada. ( ) As afirmativas I, II, III estão incorretas ( ) As afirmativas I, III, estão corretas e II errada ( ) As afirmativas II, III estão corretas e a afirmativa I está errada. 2a Questão (Ref.: 201102381492) Para fazer a modelagem de um padrão de projeto (design pattern) utilizando a UML é DESNECESSÁRIO. ( ) identificar as soluções comuns para o problema básico. PADRÕES DE PROJETO DE SOFTWARE 67 ( X ) identificar as soluções específicas e particulares para o problema básico e reificá-la como um mecanismo. ( ) entender o padrão de projeto como uma colaboraçãorepresentada com suas partes estruturais e comportamentais. ( ) fazer a modelagem do mecanismo como uma colaboração, fornecendo seus aspectos estruturais, assim como os aspectos comportamentais. ( ) identificar os elementos do padrão de projeto que devem ser vinculados aos elementos em um contexto específico e representá-los como parâmetros para colaboração. 3a Questão (Ref.: 201102422761) (FGV - 2008) Considere as seguintes assertivas sobre as vantagens do uso de padrões de software (software patterns): I. Padrões de projeto proporcionam um vocabulário comum de projeto, facilitando comunicação, documentação e aprendizado dos sistemas de software. II. P a d r õ e s d e p r o j e t o a u x i l i a m n o desenvolvimento de software por meio da reuti l ização do projeto de soluções computacionais já testadas e aprovadas. PADRÕES DE PROJETO DE SOFTWARE 68 III. Uma biblioteca de padrões pode ajudar a melhorar e padronizar o desenvolvimento de software. As assertivas corretas são: ( ) somente I e III. ( ) somente I e II. ( ) somente II e III. ( X ) I, II e III. ( ) somente II. PADRÕES DE PROJETO DE SOFTWARE 69 AULA 04 PADRÕES ESTRUTURAIS GOF (II) Nesta aula, você irá: 1.Continuar estudando padrões estruturais; 2.Conhecer os padrões de estruturais façade, proxy e flyweight; 3.Aprender as principais aplicações e funcionalidades destes padrões. Proxy Em muitas situações de programação, é possível reso lver o prob lema de acesso a um determinado objeto com a utilização de uma referência a variável desejada, este é um mecanismo de simples utilização e bastante conhecido pelos desenvolvedores de software. No entanto, quando é necessário utilizar um mecanismo mais versátil e sofisticado, por exemplo, para postergar a instanciação de um objeto, para controlar o acesso ao mesmo, para acessá-lo em uma máquina remota ou mesmo para gravá-lo em uma base de dados, a alternativa de utilizar uma referência ao objeto não é mais apropriada. Nesses casos, a utilização do padrão de projeto Proxy se mostra bastante oportuna, embora sua PADRÕES DE PROJETO DE SOFTWARE 70 utilização introduza um nível de referência adicional para acessar o objeto. A idéia é utilizar um substituto para o objeto real, mantendo a mesma interface do original sempre que for inconveniente, ou indesejável, acessá-lo diretamente. A utilização do padrão Proxy não i m p õ e f u n c i o n a l i d a d e s a d i c i o n a i s a implementação da classe original, apenas recomenda a utilização de uma superclasse abstrata para definir a interface da classe desejada e uma classe derivada adicional derivada, chamada Proxy, que irá fornecer acesso ao objeto original. Proxy - Fornece um substituto ou marcador de localização de outro objeto para controlar o acesso a esse objeto (Gamma et al, 2004). Para melhor ilustrar os conceitos apresentados, considere o digrama UML apresentado na Figura 1, a idéia é implementar um classe para controlar acesso às impressoras de uma empresa, considerando que somente poderão enviar trabalhos para impressão, usuários cadastrados e autorizados para este fim. Inicialmente, seguindo a idéia de padrão Proxy, foi definida uma classe abstrata chamada Impressora (Subject), a seguir, foram definidas PADRÕES DE PROJETO DE SOFTWARE 71 duas classes derivadas: ImpressoraUm (RealSubject) e ImpressoraProxy(Proxy). A partir dessa estrutura de classes, sempre que um cliente for instanciar uma Impressora do s i s t e m a , d e v e p r i m e i r o i n s t a n c i a r ImpressoraProxy e, a cada pedido de impressão, enviar o nome do usuário como parâmetro para validação junto ao banco de dados. Um detalhe de implementação a ser observado é que o Proxy deve oferecer a mesma interface do objeto real, de tal modo que possa substituir o objeto original. Façade Há muitas aplicações de software, onde os programadores dividem um problema complexo em diversas classes para resolvê-lo de forma gradual e modular. No entanto, embora essa prática seja bastante comum e recomendada pelos autores da área de engenharia de sof tware, não se consegue v is lumbrar PADRÕES DE PROJETO DE SOFTWARE 72 rapidamente quais funcionalidades de cada classe estão relacionadas com o problema principal e quais são os procedimentos auxiliares de cada classe, dificultando a utilização da solução proposta pelas classes clientes. Portanto, como se sabe, estruturar um sistema em subsistemas ajuda a reduzir a complexidade do problema (Gamma et al., 2000). No entanto, um objetivo comum de todos os projetos é minimizar a comunicação e as dependências entre os diferentes subsistemas. Uma das maneiras de contornar esse problema é utilizar o padrão de projeto Façade (fachada), o qual fornece uma interface única e simplificada para os recursos e facilidades mais gerais de um subsistema. PADRÕES DE PROJETO DE SOFTWARE 73 Considere, por exemplo, o diagrama UML apresentado na Figura 2. A solução proposta é simplificada e tem apenas objetivos didáticos, no e n t a n t o , d e m o n s t r a u m c o n j u n t o d e funcionalidades básicas para demonstrar o problema de conceder um empréstimo a cliente de um banco, assim como as classes básicas envolvidas no problema. PADRÕES DE PROJETO DE SOFTWARE 74 PADRÕES DE PROJETO DE SOFTWARE 75 Inicialmente, projetou-se uma classe Cliente, para armazenar os dados cadastrais, uma classe Empréstimo para armazenar os diferentes empréstimos que um cliente já realizou e uma classe auxiliar AnaliseCredito para implementar as funcionalidades de concessão de um empréstimo ou não. A o a n a l i s a r m o s e s s a s t r ê s c l a s s e s , individualmente, pode parecer difícil perceber, ao menos para um leigo no assunto, a sequência de passos que são necessários para se obter um empréstimo. Porém, ao projetarmos uma quarta classe nesse sistema, chamada Facade, podemos deixar expl íc i to todos os procedimentos para concessão de crédito e, ao mesmo tempo, o cliente passa a utilizar apenas um método i m p l e m e n t a d o n e s t a c l a s s e (realizarEmprestimo). ATENÇÃO Entre outras vantagens da solução proposta, o cliente não precisa conhecer todas as regras de negóc io envo l v i das com a concessão de um empréstimo, PADRÕES DE PROJETO DE SOFTWARE 76 além disso, havendo mudança em alguma regra de negócio, basta realizar as alterações necessárias na classe Façade, o cliente também fica imune a este tipo de mudança. Vantagens da classe Façade A classe Façade, em qualquer contexto, tem como objetivo mais amplo buscar respostas para um problema de forma transparente em um conjunto de subsistemas e fornecer uma resposta imediatapara a classe cliente. Entre as principais vantagens desse padrão de projeto pode-se citar: 1.Tornar os c l ientes independentes da complexidade dos diferentes subsistemas de uma aplicação. 2.Incent ivar acoplamento fraco entre o subsistema e seus clientes. 3.Ajudar a melhorar portabilidade dos sistemas. 4.Simpl ificar o acesso a determinadas funcionalidades de um subsistema, sem inviabilizar sua utilização direta. PADRÕES DE PROJETO DE SOFTWARE 77 Flyweight Antes de qualquer comentário sobre o padrão de projeto Flyweight, é importante destacar as palavras granularidade fina na definição acima, elas são fundamentais para entender o escopo e funcionalidade deste padrão de projeto, pois, este padrão está relacionado a objetos simples e com poucas funcionalidades. Além disso, normalmente, esse padrão de projeto está relacionado àqueles objetos que aparecem em grande número na aplicação, que precisam ser instanciados inúmeros vezes com os mesmos atributos. O objetivo do Flyweight é diminuir o consumo de memória, porém deve ser utilizado com cautela; Gamma et al (2000) recomendam sua utilização somente quando todas as condições abaixo forem verdadeiras: 1.Uma aplicação utiliza um grande número de objetos. 2.Os custos de armazenamento são altos por causa da grande quantidade de objetos. 3.Muitos grupos de objetos podem ser substituídos por relativamente poucos objetos comparti lhados, uma vez que estados extrínsecos são removidos. PADRÕES DE PROJETO DE SOFTWARE 78 4.A aplicação não depende da identidade do objeto. Um exemplo que ajuda a ilustrar a aplicabilidade deste padrão de projeto é uma aplicação web. Considere, por exemplo, um site de comércio eletrônico e o diagrama de classes apresentados na Figura 3. Podemos supor que existem diversos tipos de usuários que fazem uso deste sistema (PapelSistema_A). Inicialmente, cada usuário deve ser cadastrado e um perfil para acesso ao sistema é associado com cada um deles. Por exemplo, os fornecedores dos produtos podem diretamente acessar o site e atualizar o sistema com novas informações e promoções relâmpagos, podem alterar preços, prazos de entrega e formas de pagamento. PADRÕES DE PROJETO DE SOFTWARE 79 PADRÕES DE PROJETO DE SOFTWARE 80 Por outro lado, um cliente, previamente cadastrado no site, terá somente a informações sobre histórico de pedidos, rastreamento, informações on line através de chat, entre outros. Por último, para simplificar, um visitante qualquer, ao acessar o site apenas para consultar produtos e ofertas, terá uma lista menor de funcionalidades a disposição, mas também terá um perfil padrão com permissões e restrições. Portanto, podemos definir três tipos de usuários para esse sistema: Administrador, Cliente e Visitante, cada qual, com diferentes n í v e i s d e a c e s s o e c o m d i f e r e n t e s funcionalidades a seu dispor. Vamos supor, ainda, que esse site apresenta um grande número de anunciantes e que também receba um número considerável de visitas a cada dia. Portanto, se formos instanciar um novo perfil (FlyweightPapel), cada vez que se estabelecer uma conexão com o site, o número de instâncias dessa classe será bastante grande, requerendo uma boa quantidade de espaço de memória. Porém, há uma solução alternat iva de implementação; este problema se mostra bastante apropriado para aplicarmos a idéia do PADRÕES DE PROJETO DE SOFTWARE 81 padrão de projeto Flyweight- faça o teste das condições mencionadas acima. Assim, ao invés de instanciar um objeto perfil para cada usuário que acessa ao site, vamos instanciar cada perfil apenas uma vez (ver construtor da classe FlyweightFactory) e compartilhar o perfil criado com cada usuário que se conectar ao site. Essa solução apresenta consumo de memória de tamanho fixo (quando se referimos a alocar perfil dos usuários), pois, sempre estaremos alocando, no exemplo em questão, no máximo 3 instâncias da classe FlyweightPapel e não uma instância para cada usuário que acessar o site. Nesta aula, você: •Estudou os três padrões estruturais restantes da gof: façade, flyweight e proxy. •Identificou as situações onde cada um deles deve ser aplicado. •Estudou três exemplos práticos com a utilização destes padrões. PADRÕES DE PROJETO DE SOFTWARE 82 AULA 05 PADRÕES COMPORTAMENTAIS GOF (I) Nesta aula, você irá: 1.Iniciar o estudo da família de padrões comportamentais gof. 2.Conhecer os padrões comportamentais chain of responsability, interpreter e template method. 3.Aprender as pr inc ipa is ap l icações e funcionalidades destes padrões. Interpreter ➡ O padrão de projeto Intepreter descreve como projetar um conjunto de classes para representar e interpretar uma gramática para linguagens simples. Sua aplicação é recomenda naquelas situações em que há necessidade de interpretar uma linguagem qualquer e, ao mesmo tempo, quando se quer representar sentenças da linguagem, como árvores abstratas sintáticas. É i m p o r t a n t e d e s t a c a r q u e o t e r m o “linguagem”, na definição desse padrão, é bastante ampla, não estando restrita apenas a linguagens de programação, como na maioria dos exemplos apresentados. PADRÕES DE PROJETO DE SOFTWARE 83 Intepreter - Dada uma linguagem, definir uma representação para a sua gramática, juntamente com um interpretador, que usa a representação para interpretar sentenças dessa linguagem (Gamma et al., 2000). ➡ Para ampliar nossa visão, o exemplo apresentado na Figura 1 apresenta uma aplicação bastante didática, embora pouco usual, para exemplificar os elementos principais desse padrão de projeto. No e x e m p l o a p r e s e n t a d o , p r o c u r a - s e demonstrar também a estreita relação do padrão Interpreter com o padrão de projeto Composite, apresentado na Aula 3, compare os exemplos e verifique as semelhanças de modelagem, procure também reconhecer que a árvore sintática abstrata do padrão de projeto Interpreter é uma instância do padrão Composite. ➡ A estrutura do padrão Interpreter sugere que a modelagem do problema seja realizada através de uma gramática recursiva. Nesse caso, cada regra gramatical pode ser representada através de dois elementos principais: (1) como um “Composite” e (2) PADRÕES DE PROJETO DE SOFTWARE 84 como um terminal, ou seja, um nodo folha em uma estrutura de árvore. O padrão Interpreter realiza sucessivas chamadas recursivas ao padrão Composite (nodos não terminais) para interpretar as sentenças, até chegar em nodos terminais. ➡ O exemplo apresentado na Figura 1 utiliza o padrão de pro je to In terpre ter para representar e interpretar uma música. Inicialmente, é definido uma classe abstrata Melodia (AbstractExpression), a partir da qual são definidas duas classes derivadas: Partitura e NotaMusical. Uma partitura é uma representação formal e escrita de uma PADRÕES DEPROJETO DE SOFTWARE 85 música que dispõe de diferentes símbolos (notas musicais) que estão associados a sons. Dessa forma, para “tocar” uma música, basta percorrer a estrutura de dados formada com a utilização do padrão de projeto Interpreter e interpretá-la, tocando os sons conforme os dados armazenados na classe NotaMusical. ➡ Mais uma vez, cabe destacar que é importante visualizar, a partir do exemplo anterior, que a estrutura do padrão Interpreter sugere que a modelagem do problema seja realizada através de uma gramática recursiva. Caso o leitor não tenha fami l ia r idade com es tes conce i tos , normalmente relacionados com a área de Compiladores e Linguagens Formais, procure alguma referência sobre este assunto ou consulte Aho et al. (1995). ➡ Mais uma vez, cabe destacar que é importante visualizar, a partir do exemplo anterior, que a estrutura do padrão Interpreter sugere que a modelagem do problema seja realizada através de uma gramática recursiva. Caso o leitor não tenha fami l ia r idade com es tes conce i tos , PADRÕES DE PROJETO DE SOFTWARE 86 normalmente relacionados com a área de Compiladores e Linguagens Formais, procure alguma referência sobre este assunto ou consulte Aho et al. (1995). ➡ Para Gamma et al. (2000) entre as vantagens do padrão Interpreter podem-se citar: (1) facilidade para mudar e estender a gramática, pois, o padrão utiliza classes para representar as regras gramaticais. Pode-se usar herança para mudar ou estender a gramát ica, ass im como expressões e x i s t e n t e s p o d e m s e r m o d i fi c a d a s incrementalmente e novas expressões podem ser criadas a partir das existentes; (2) a implementação da gramática é mais fácil, pois, classes que definem os nós folhas da árvore tem implementações similares. Por outro lado, uma das desvantagens é que o padrão Interpreter define, ao menos, uma classe para cada regra da gramática, logo, gramáticas com muitas regras são difíceis de manter e administrar. PADRÕES DE PROJETO DE SOFTWARE 87 Template Method O padrão de projeto Template Method sugere a implementação de um algoritmo que faz uso de diferentes métodos, diferenciando das soluções convencionais por deixar o esqueleto deste algoritmo fixo em uma superclasse abstrata. Os demais métodos, chamados na definição do padrão de PrimitiveOperation, podem ser redefinos nas classes derivadas para oferecer diferentes alternativas de implementação do “esqueleto” proposto, ou seja, implementar um comportamento concreto aos métodos que foram definidos como abstratos na superclasse. Template Method Definir o esqueleto de um algoritmo em uma operação, postergando alguns passos para subclasses. Template Method permite que subclasses redefinam certos passos de um algoritmo sem mudar a estrutura do mesmo (Gamma et al., 2004). A vantagem dessa estrutura é que se consegue alterar o comportamento de um algoritmo, sem modificar sua estrutura lógica. Dessa forma, as partes invariantes de um algoritmo são implementadas uma única vez na superclasse (abstrata), enquanto que as partes que podem PADRÕES DE PROJETO DE SOFTWARE 88 variar, conforme a situação, contexto ou problema a ser resolvido, são redefinas nas classes derivadas (concretas). A imagem apresenta um exemplo para demonstrar a aplicação desse padrão de projeto em um algoritmo que tem como objetivo validar um usuário para acesso a uma aplicação. Inicialmente, foi especificado uma superclasse abstrata chamada ValidarUsuario (AbstractClass) e duas classes derivadas, a primeira chamada PessoaFisica (ConcretClass) e a segunda chamada PessoaJuridica (ConcretClass). A classe ValidarUsuario apresenta três métodos, o primeiro deles (TemplateMethod) apresenta um algoritmo fixo, conforme é sugerido pelo padrão de projeto, que utiliza dois métodos auxiliares para sua implementação. O primeiro, para validar o dígito verificador (verificarDV) e PADRÕES DE PROJETO DE SOFTWARE 89 segundo, para verificar se o usuário está cadastrado no banco de dados do sistema (verificarCadastro). De acordo com o exemplo, pode-se verificar que o algoritmo base é sempre o mesmo, sendo válido para as duas situações (pessoa física e jurídica), porém, cada uma das classes derivadas pode redefinir os demais métodos de acordo com suas especificidades. Chain of Responsability A implementação do padrão de projeto Chain of Responsability requer que cada objeto receptor de uma determinada solicitação tenha uma lógica para descrever os tipos de solicitação que é capaz de processar e como passar adiante aquelas que requeiram processamento por outros receptores. A delegação das solicitações pode formar uma árvore de recursão, com um mecanismo especial para inserção de novos receptores no final da cadeia existente. Chain of Responsability Evitar o acoplamento do remetente de uma solicitação ao seu receptor, ao d a r a m a i s d e u m o b j e t o a oportunidade de tratar a solicitação. Encadear os objetos receptores, passando a solicitação ao longo da PADRÕES DE PROJETO DE SOFTWARE 90 cadeia até que um objeto a trate (Gamma et al., 2000). A imagem apresenta um exemplo para ilustrar a aplicabilidade deste padrão de projeto. A ideia é projetar um módulo de um sistema web para a tender as so l ic i tações dos usuár ios , oferecendo, pelo menos, quatro opções de contato: informações sobre pagamento, suporte técnico, sugestão ou vendas de novos produtos. Dependendo da área escolhida, um especialista será alocado para atender a solicitação. A classe Handler Utilizando a estrutura do padrão de projeto Chain of Responsability, definiu-se, inicialmente, uma classe abstrata chamada Handler com um método responsável por atender requisições (atenderRequisicao) e outro para setar o sucessor (setSucessor). Vejam que o sucessor é PADRÕES DE PROJETO DE SOFTWARE 91 uma referência para a própria classe, dessa forma, é possível montar uma cadeia de instâncias da classe Handler como se fosse uma lista simplesmente encadeada. A classe Handler é uma classe abstrata, portanto, não pode ser instanciada diretamente. Assim, para montar uma cadeia de objetos é necessário especializá-la em classes concretas, as quais estão representadas no diagrama da imagem, como as classes Pagamentos, Suporte, Sugestão e Vendas. PADRÕES DE PROJETO DE SOFTWARE 92 Gamma et al. (2000) destacam os seguintes benefícios do padrão de projeto Chain of Responsability: 1. O acoplamento é reduzido, pois, o padrão libera um objeto de ter que conhecer qual o outro objeto que trata de uma solicitação. Além disso, tanto remetente como receptor não têm conhecimento explícito um do outro; 2. Reduz a interconexão entre os objetos, ao invés de um objeto manter uma lista
Compartilhar