Flávio Pernes de Medeiros - PDF
Download "Flávio Pernes de Medeiros"
Maria do Pilar Guimarães César
1 Flávio Pernes de Medeiros METODOLOGIA DA PESQUISA II Rio de Janeiro Flávio Pernes de Medeiros Março de 2011
2 Agradecimentos A minha família em especial minha esposa Newli Maura e filhos Bruno e Nicole. Aos professores em especial ao Oswaldo Borges. A Deus, pelo dom da vida. ii
3 RESUMO Um padrão de projeto é uma estrutura recorrente no projeto de software orientado a objetos. Pelo fato de ser recorrente, vale a pena que seja documentada e estudada. Um padrão de projeto nomeia, abstrai e identifica os aspectos chave de uma estrutura de projeto comum para torná-la útil para a criação de um projeto orientado a objetos reutilizável. Palavras-Chave: Java, Padrões, Design, Patterns, Reuso. ii
4 ABSTRACT Design Patterns describe solutions to recurring problems in developing systems of object-oriented software. A design pattern provides a name and define the problem, the solution when this solution and its consequences. The design patterns to facilitate reuse of design solutions - that is, solutions in the design phase of the software, without considering code reuse. They will also carry a common vocabulary of design, facilitating communication, learning and documentation of software systems. iv
5 Padrões de projeto Estrutural Monografia apresentada à Universidade Estácio de Sá, como requisito final do curso de pós-graduação em Desenvolvimento de sistemas - JAVA. Orientador: Prof. JOÃO MENDES Rio de Janeiro 03/2011 v
6 Sumário 1 Introdução Tema Delimitação Justificativa Objetivos Metodologia Descrição Descobrindo padrões no projeto Principal alvo Abstrações Como escolher o padrão certo Padrões de projeto em detalhes Adapter Quando usar Classe adapter Objeto adapter Onde estão os adapters Duas formas de Adapter Objeto Adapter Implemantação em Java do padrão adapter vi
7 3.2 - Bridge Motivação Aplicabilidade Vantagens Implementação Composite Motivação Aplicabilidade Vantagens Implementação Decorator Motivação Aplicabilidade Estrutura Implementação Vantagens Façade Motivação Aplicabilidade Estrutura Participantes Vantagens Implementação Flyweight Motivação Aplicabilidade Vantagens vi
8 3.6.4 Implementação Conseqüências Proxy Motivação Aplicabilidade Vantagens Conseqüências Implementação Conclusão 33 Bibliografia 34 vi
9 Lista de Figuras 3.1 Exemplo da representação do padrão de projeto adapter Exemplo da representação do padrão de projeto adapter com herança múltipla Exemplo da representação do padrão de projeto adapter usando composição Exemplo de implementação java do padrão de projeto adapter Exemplo estrutural do padrão de projeto bridge Exemplo da aplicação do padrão de projeto bridge Estrutura do padrão de projeto composite Estrutura do padrão decorator Exemplo de aplicação Exemplo de herança Exemplo de uso com interface Exemplo de uso de interface com herança Exemplo de uso facade para casos complexos flyweights padrão proxy. 32 ix
10 Capítulo 1 Introdução 1.1 Tema Com a maturidade na engenharia de softwares, novos aspectos e novas abordagens foram surgindo até atingirmos o que chamamos de padrões de projetos. Seu uso busca o mapeamento de soluções para problemas similares e ou conhecidos, ao invés de se desenvolver soluções a cada novo problema, busca-se primeiro identificar os problemas e aplicar a solução conhecida, diminuindo assim, erros, tempo de construção e praticando reuso. Neste trabalho abordaremos a aplicabilidade dos padrões estruturais. O conceito de padrão de projeto foi criado na década de 70 pelo arquiteto Christopher Alexander.[1] Em seus livros, ele estabelece que um padrão deve ter, idealmente, as seguintes características: No presente trabalho iremos detalhar apenas o padrão estrutural. Encapsulamento: um padrão encapsula um problema/solução bem definida. Ele deve ser independente, específico e formulado de maneira a ficar claro onde ele se aplica. Generalidade: todo padrão deve permitir a construção de outras realizações a partir deste padrão. Equilíbrio: quando um padrão é utilizado em uma aplicação, o equilíbrio dá a razão, relacionada com cada uma das restrições envolvidas, para cada passo do projeto. Uma análise racional que envolva uma abstração de dados empíricos, uma observação da 1
11 aplicação de padrões em artefatos tradicionais, uma série convincente de exemplos e uma análise de soluções ruins ou fracassadas pode ser a forma de encontrar este equilíbrio. Abstração: os padrões representam abstrações da experiência empírica ou do conhecimento cotidiano. Abertura: um padrão deve permitir a sua extensão para níveis mais baixos de detalhe. Combinatoriedade: os padrões são relacionados hierarquicamente. Padrões de alto nível podem ser compostos ou relacionados com padrões que endereçam problemas de nível mais baixo. Além da definição das características de um padrão, Alexander definiu o formato que a descrição de um padrão deve ter. Ele estabeleceu que um padrão deve ser descrito em cinco partes: Nome: uma descrição da solução, mais do que do problema ou do contexto. Exemplo: uma ou mais figuras, diagramas ou descrições que ilustrem um protótipo de aplicação. Contexto: a descrição das situações sob as quais o padrão se aplica. Problema: uma descrição das forças e restrições envolvidos e como elas interagem. Solução: relacionamentos estáticos e regras dinâmicas descrevendo como construir artefatos de acordo com o padrão, freqüentemente citando variações e formas de ajustar a solução segundo as circunstâncias. Inclui referências a outras soluções e o relacionamento com outros padrões de nível mais baixo ou mais alto. Em 1987, a partir dos conceitos criados por Alexander, os programadores Kent Beck e Ward Cunningham propuseram os primeiros padrões de projeto para a área da ciência da computação. Em um trabalho para a conferência OOPSLA, eles apresentaram alguns 2
12 padrões para a construção de janelas na linguagem Smalltalk.[2] Nos anos seguintes Beck, Cunningham e outros seguiram com o desenvolvimento destas idéias. O movimento ao redor de padrões de projeto ganhou popularidade com o livro Design Patterns: Elements of Reusable Object-Oriented Software, publicado em Os autores desse livro são Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides, conhecidos como a "Gangue dos Quatro" (Gang of Four) ou simplesmente "GoF". Posteriormente, vários outros livros do estilo foram publicados, como Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development, que introduziu um conjunto de padrões conhecidos como GRASP (General Responsibility Assignment Software Patterns). 1.2 Delimitação Neste trabalho iremos abordar os tipos de problemas e a forma correta de uso e aplicabilidade dos padrões de projeto, embora haja 23 padrões de projeto, classificados em 3 grandes grupos: Criacionais, Estruturais e Comportamentais, o foco do nosso trabalho será o padrão Estrutural. 3
13 1.3 Justificativa É evidente que ao seguir padrões de desenvolvimento, as equipes acabarão trazendo aspectos positivos para seus projetos, além de tornar seus softwares mais fáceis de manter, conseqüentemente reduzindo seu tempo e custo de manutenção. 1.4 Objetivos Existem vários objetivos e com a aplicabilidade de padrões de projeto, Os softwares só tendem a ganhar, não importa o tamanho do projeto, pode ser um pequeno projeto ou um grande projeto, seguir padrões sempre acabará trazendo vantagens, as principais que podemos citar são: Facilidade na manutenção; Melhoria da documentação; Melhora a visão geral do sistema; Melhora a leitura e entendimento do código; Facilita o desenvolvimento com equipes grandes; Permite que seus códigos sejam facilmente entendidos por outros, além de você. 4
14 1.5 Metodologia Este trabalho foi realizado mediante pesquisas e levantamento de material bibliográfico, além de consultas a informações constantes na internet, tendo como enfoque artigos científicos e aplicações atuais que tratassem sobre o tema abordado. 1.6 Descrição Além deste primeiro capítulo introdutório, no capítulo dois definimos e contextualizamos os padrões de projeto dentro do processo de desenvolvimento de softwares. No capítulo três descrevemos as técnicas e classificação dos padrões, bem como suas aplicabilidades. No capitulo quatro evidenciamos nossas conclusões. 5
15 Capítulo 2 Descobrindo padrões no projeto 2.1 Principal alvo O alvo principal do uso dos padrões de projeto no desenvolvimento de software é o da orientação a objetos. Como os objetos são os elementos chaves em projetos OO, a parte mais difícil do projeto é a decomposição de um sistema em objetos. A tarefa é difícil porque muitos fatores entram em jogo: encapsulamento, granularidade, dependência, flexibilidade, desempenho, evolução, reutilização e assim por diante. Todos influenciam a decomposição, freqüentemente de formas conflitantes. [3] Muito dos objetos participantes provêm do método de análise. Porém, projetos orientados a objetos acabam sendo compostos por objetos que não possui uma contrapartida no mundo real. 2.2 Abstrações As abstrações que surgem durante um projeto são as chaves para torná-lo flexível. Os padrões de projeto ajudam a identificar abstrações menos óbvias bem como os objetos que podem capturá-las. Por exemplo, objetos que representam processo ou algoritmo não ocorrem na natureza, no entanto, eles são uma parte crucial de projetos flexíveis. Esses objetos são raramente encontrados durante a análise ou mesmo durante os estágios iniciais de um projeto; eles são descobertos mais tarde, durante o processo de tornar um projeto mais flexível e reutilizável. 6
16 2.3 Como escolher o padrão certo Escolher dentre os padrões existentes aquele que melhor soluciona um problema do projeto, sem cometer o erro de escolher de forma errônea e torná-lo inviável, é uma das tarefas mais difíceis. Em suma, a escolha de um padrão de projeto a ser utilizado, pode ser baseada nos seguintes critérios: Considerar como os padrões de projeto solucionam problemas de projeto. Examinar qual a intenção do padrão, ou seja, o que faz de fato o padrão de projeto, quais seus princípios e que tópico ou problema particular de projeto ele trata (soluciona). Estudar como os padrões se relacionam. Estudar as semelhanças existentes entre os padrões. Examinar uma causa de reformulação de projeto Considerar o que deveria ser variável no seu projeto, ou seja, ao invés de considerar o que pode forçar uma mudança em um projeto, considerar o que você quer ser capaz de mudar sem reprojetá-lo. 7
17 Capítulo 3 Padrões de projeto em detalhes Padrões estruturais 3.1 Adapter "Objetivo: converter a interface de uma classe em outra interface esperada pelos clientes. Adapter permite a comunicação entre classes que não poderiam trabalhar juntas devido à incompatibilidade de suas interfaces." [4] Quando usar Sempre que for necessário adaptar uma interface para um cliente Classe Adapter Quando houver uma interface que permita a implementação estática Objeto Adapter Quando menor acoplamento for desejado. Quando o cliente não usa uma interface Java ou classe abstrata que possa ser estendida Onde estão os adapters A API do J2SDK. 8
18 9 Figura 3.1 Exemplo da representação do padrão de projeto adapter.
19 3.1.5 Duas formas de Adapter Classe Adapter: usa herança múltipla Figura Exemplo da representação do padrão de projeto adapter com herança multipla. Cliente: aplicação que colabora com objetos aderentes à interface Alvo Alvo: define a interface requerida pelo Cliente Classe Existente: interface que requer adaptação Adaptador(Adapter): adapta a interface do Recurso à interface Alvo Objeto Adapter: usa composição Figura Exemplo da representação do padrão de projeto adapter usando composição. 10
20 Única solução se Alvo não for uma interface Java Adaptador possui referência para objeto que tera sua interface adaptada (instância de Classe Existente). Cada método de Alvo chama o(s) método(s) correspondente(s) na interface adaptada Implemantação em Java do padrão adapter Classe Adapter: Figura Exemplo de implementação java do padrão de projeto adapter. 11
21 3.2 Bridge "Desacoplar uma abstração de sua implementação para que os dois possam variar independentemente." [4] Motivação: O que motiva a utilização do padrão Bridge é a necessidade de um driver, permitindo implementações específicas para tratar objetos em diferentes meios persistentes Aplicabilidade: Quando for necessário evitar uma ligação permanente entre a interface e a implementação. Quando alterações na implementação não puderem afetar clientes. Quando implementações são compartilhadas entre objetos desconhecidos do cliente. Figura 3.2 Exemplo estrutural do padrão de projeto bridge. 12
22 3.2.3 Vantagens Detalhes de implementação totalmente inacessíveis aos clientes. Eliminação de dependências em tempo de compilação das implementações. Implementação de abstração pode ser configurada em tempo de execução Implementação: A implementação (adaptado [5]) do Padrão Bridge ilustra a Ponte entre a classe abstrata ObetoNegocios a ClienteDadosObjeto através de interface DadosObjeto. A interface DadosObjeto não é igual a ObjetoNegocios, já que não existe necessária dependência entre elas. Este exemplo demonstra desacoplamento de uma abstração de ObjetoNegocio da implementação em DadosObjeto. As implementações de DadosObjeto podem evoluir dinamicamente sem propagar mudanças a nenhum dos objetos cliente, isso pode ser verificado na figura Na classe ClienteDadosObjeto encontra-se a implementação que a classe cliente espera através da DadosObjeto, neste caso, ela contém algumas pessoas cadastradas, ela pode adicionar novas pessoas em determinado grupo ou mostrá-las. Para interagir entre os cadastros utiliza-se o Padrão Iterator, que será detalhado nos próximos Padrões. 13
23 14 Figura Exemplo da Aplicação do Padrão de Projeto Bridge
24 3.3 Composite Compõe objetos em estruturas do tipo árvore para representar hierarquias todo-parte. Faz também com que o tratamento dos objetos individuais e de suas composições seja uniforme Motivação Aplicações gráficas como editores de desenho e sistemas de captura de esquema deixam os usuários construírem diagramas complexos a partir de Componentes simples. O usuário pode agrupar Componentes para formar Componentes maiores, que, por sua vez, podem ser agrupados para formar Componentes maiores ainda. O Padrão Composite descreve como usar composição recursiva, de modo que os clientes não tenham que fazer distinção entre componentes simples e composições Aplicabilidade Use o Padrão de Projeto Bridge quando: Quiser representar hierarquias parte-todo de objetos; Deseja que os clientes sejam capazes de ignorar as diferenças entre composição de objetos e objetos individuais. Clientes tratarão todos os objetos uniformemente na estrutura Composite Vantagens Objetos complexos podem ser compostos de objetos mais simples recursivamente. Facilita a adição de novos componentes. 15
25 3.3.4 Implementação Componente: Declara a interface para objetos na composição; Implementa comportamento default para interface comum a todas as classes, como apropriado; Declara uma interface para acessar ou gerenciar seus Componentes filhos; Folha: Representa objetos folhas na composição. Uma folha não tem filhos; Define comportamento para objetos primitivos na composição. Composição: Define comportamento para Componentes que têm filhos; Armazena Componentes filhos; Implementa operações relacionadas com filhos na interface do Componente. Cliente: Manipula objetos na composição através da interface Componente Figura 3.3 Estrutura do Padrão de Projeto Composite 16
26 3.4 Decorator Agregar responsabilidades adicionais a um objeto dinamicamente. Classes decoradoras oferecem uma alternativa flexível ao uso de herança para estender uma funcionalidade [5] Motivação Adicionar responsabilidades a um objeto, mas não à sua classe. Acontece, por exemplo, com criação de interfaces gráficas, quando se deseja acrescentar uma borda a um componente qualquer ou uma barra de rolagem a uma área de texto. Uma abordagem mais flexível é inserir o componente em outro objeto que adiciona a borda, um Decorator [5] Aplicabilidade Utilizado para adicionar responsabilidades a objetos individuais de forma dinâmica e transparente, isto é, sem afetar outros objetos, da mesma forma, quando se quer retirar responsabilidades. Quando a utilização de heranças para a implementação do mesmo afetará a flexibilidade do sistema [6]. Um caso de aplicação do Decorator é quando existem muitas variações de um objeto. Imagine por exemplo uma classe Janela com uma subclasse JanelaComBorda. Se houver a necessidade também de janelas com rolagem, tem-se ainda JanelaComRolagem e JanelaComBordaERolagem [6], além de outras possíveis combinações, já que poderia haver menus, botões ou barra de status. 17
27 Usando o Decorator, tem-se um número muito menor de subclasses: Janela, DecoratorJanela, DecoratorJanelaBorda, DecoratorJanelaRolagem, DecoratorJanelaMenu, e assim por diante [6] Estrutura Esse padrão providencia que cada objeto Decorator contenha outro objeto Decorator. Nesse aspecto, um decorator é como um pequeno composite cujos elementos possuem cada qual um filho único. Diferentemente do padrão Composite, cujo propósito é compor objetos agregados, o propósito do Decorator é compor comportamentos Implementação Componente : define a interface para objetos que podem ter responsabilidades acrescentadas a eles dinamicamente. ComponenteConcreto : define um objeto para o qual responsabilidades adicionais podem ser atribuídas Decorator : mantém uma referência para um objeto Componente. Define uma interface que segue a interface de Componente. DecoratorConcretoA e DecoratorConcretoB: acrescenta responsabilidades ao componente 18
28 Figura 3.4 Estrutura do padrão Decorator Vantagens: Fornece uma flexibilidade maior do que a herança estática. Evita a necessidade de colocar classes sobrecarregadas de recursos em uma posição mais alta da hierarquia. Simplifica a codificação permitindo que você desenvolva uma série de classes com funcionalidades específicas, em vez de codificar todo o comportamento no objeto. Aprimora a extensibilidade do objeto, pois as alterações são feitas codificando novas classes. 19
29 3.4.5 Implementação Figura exemplo de aplicação O exemplo ilustrado na Figura 3.4.1, visa gerar janelas com características que podem variar de uma janela para outra. Por exemplo, o cliente pode decidir entre construir uma janela com barra de menus ou não. Desta forma consegue-se aumentar o número de possibilidades de janelas diferentes apresentadas com um pequeno número de classes. Neste exemplo, a interface Janela recebe o papel de ser o Componente da estrutura apresentada anteriormente. Por sua vez, JanelaComum interpreta o ComponenteConcreto, ou seja, é ele que receberá as modificações no decorrer da execução da aplicação. Como o próprio nome diz, o Decorator assume a finalidade do Decorator da estrutura padrão. JanelaMenuBar, JanelaBorda, JanelaBarraStatus e JanelaBarraFerramenta herdam de Decorator, ou seja, são os n decoradores concretos. 20
30 3.5 Façade Oferecer uma interface única para um conjunto de interfaces de um subsistema. Definir uma interface de nível mais elevado que torna o subsistema mais fácil de usar [5]. Reduzir a complexidade do relacionamento entre uma classe relativa ao cliente e as demais classes utilitárias [5] Motivação: Uma grande vantagem da programação orientada a objetos é que ela ajuda a evitar que as aplicações se tornem programas monolíticos, com pedaços incorrigivelmente entrelaçados. No entanto, a aplicabilidade variada das classes em um subsistema orientado a objetos pode oferecer uma variedade expressiva de opções [7]. Existem circunstâncias onde é necessário utilizar diversas classes diferentes para que uma tarefa possa ser completada, caracterizando uma situação onde uma classe cliente necessita utilizar objetos de um conjunto específico de classes utilitárias que, em conjunto, compõem um subsistema particular ou que representam o acesso a diversos subsistemas distintos [7], como ilustrado na Figura abaixo. 21
31 Figura 3.5 exemplo de herança Aplicabilidade Criação de interfaces mais simples para um ou mais subsistemas complexos. Redução de dependência entre o cliente e as classes existentes nos subsistemas, ocasionando a redução da coesão do sistema Criação de sistemas em camadas. Este padrão provê o ponto de entrada para cada camada (nível) do subsistema Estrutura A estrutura deste padrão, apresentado nas figuras Facade e Facade 3.5.2, é bastante simples. A classe que constituirá o Facade deverá oferecer um conjunto de operações que sejam suficientes para que seus clientes possam utilizar adequadamente o subsistema, embora sem conhecer as interfaces de seus componentes [6]. O Facade é um padrão que pode apresentar infinidades de formas de representá-lo. O que importa para este padrão é que o Cliente apenas acesse objetos da classe Facade, esperando algum resultado vindo dela. A classe Facade é que terá a responsabilidade de entrar em contato com as diversas instâncias dentro deste sistema, efetuar possíveis cálculos vindos de classes abaixo dela e retornar as respostas que o cliente pediu. 22
32 23 Figura facede exemplo de uso com interface
33 Figura facade exemplo de uso de interface com herança Participantes Cliente : aguarda respostas da interação do Facade e as Classes do subsistema. Facade : conhece quais classes do subsistema seriam responsáveis pelo atendimento de uma solicitação e delega solicitações de clientes a objetos apropriados dos subsistemas. Classes de subsistema : (ClasseA,..., ClasseB) Implementam as funcionalidades do subsistema. Respondem a solicitações de serviços da Facade. 24
34 Não têm conhecimento da Facade Vantagens: Protege os clientes da complexidade dos componentes do subsistema; Promove acoplamento fraco entre o subsistema e seus clientes; Reduz dependências de compilação, possivelmente complexas ou circulares; Facilita a portabilidade do sistema [5]; Reduz a união entre subsistemas desde que cada subsistema utilize seu próprio padrão Facade e outras partes do sistema utilizem o padrão Facade para comunicar-se com o subsistema [5]; Não evita que aplicações possam acessar diretamente as subclasses do sistema, se assim o desejarem [5]; Implementação: Implementar um Facade demanda definir um conjunto de operações reduzidas que permita ocultar a complexidade inerente à utilização de várias classes de um subsistema (adaptado [5]). 25
35 Figura exemplo de uso facade para casos complexos. Neste exemplo, ilustrado na Figura 3.5.3, o cliente necessita consultar várias entidades a fim de saber se têm condições de receber um empréstimo. Para isso, normalmente, o cliente teria que conhecer toda a complexidade envolvida com as regras de concessão de empréstimos e aprende-las, no entanto, nada melhor do que deixar isso a cargo de quem já está no sistema, no caso o Facade, que irá se preocupar em colher dados das diferentes classes que podem decidir sobre a possibilidade do empréstimo e retornará esta informação pronta para o cliente. FacadeApp é o cliente que busca informações que podem vir de vários de subsistemas, Facade é a classe responsável por acessar os subsistemas e trazer respostas de forma transparente a quem esteja acessando o Facade. Banco, Emprestimo, Crédito e Consumidor são classes pertencentes aos subsistemas. 26
36 3.6 Flyweight Motivação: O padrão de projeto Flyweight é um padrão estrutural que tem por finalidade usar de compartilhamento de objetos de granularidade fina, isto é, objetos que são iguais exceto pequenos detalhes. Este padrão procura fatorar as informações comuns a diversos objetos em um único componente. Os demais dados, que tornam tais objetos únicos, passam a ser utilizados como parâmetros de métodos [7]. Utilizando desse padrão é possível reduzir consideravelmente o número de objetos em uma aplicação devido ao fato de que objetos com as mesmas características são unificados em apenas um. Porém é importante ressaltar que esse padrão é indicado quando se tem uma aplicação com um número considerável de objetos que podem ser compartilhados, além de essa aplicação não depender da quantidade de objetos. Existem dois estados dos objetos que devem ser levados em conta na adoção do padrão flyweight, os estados intrínseco e extrínseco. O primeiro diz respeito à parte do objeto que será imutável independente do cliente, estará armazenado no objeto Flyweight e é o estado que será compartilhado. O segundo está relacionado à parte do objeto que será mutável e estará armazenado no cliente. 27
37 3.6.2 Aplicabilidade: A aplicação usa uma grande quantidade de objetos. Custos de armazenamento são altos, por causa da imensa quantidade de objetos. Parte considerável do estado do objeto pode ser tornar extrínseco uma vez que o estado extrínseco é removido, muitos agrupamentos de objetos podem ser substituídos por uma quantidade consideravelmente menor de objetos compartilhados. A aplicação não depende de identidade de objetos. Visto que flyweights podem ser compartilhados, testes de identidade irão retornar true para objetos conceitualmente distintos Vantagens: A principal conseqüência do uso do padrão Flyweight é a economia de memória devido à redução do número de instâncias e quantidades de estado intrínseco. [8] Podem ser introduzidos custos em termos de eficiência devido à transferência, procura e/ou computação do estado extrínseco [...], devido a isso antes de se adotar esse padrão de projeto é importante avaliar se a quantidade de memória economizada compensa realmente a possível perda de eficiência. 28
38 3.6 flyweights Implementação: Participantes : Flyweight :Declara uma interface através da qual os objetos flyweight podem receber seu estado extrínseco. ConcreteFlyweight (Caracter) : Implementa a interface Flyweight e adiciona os atributos para guarder o estado extrínseco, se houver algum. Um objeto ConcreteFlyweight precisa ser compartilhavel. Qualquer estado que ele guarde precisa ser intrínseco, ou seja, precisa ser idependente do contexto do objeto ConcreteFlyweight. UnsharedConcreteFlyweight (Linha, Coluna) : Nem todas as subclasses de Flyweight precisam ser compartilhadas. A interface Flyweight permite o compartilhamento, mas não obriga. É comum para a classe UnsharedConcreteFlyweight ter a classe ConcreteFlyweight como filha em algum nível da estrutura de classes do flyweight. 29
39 FlyweightFactory :Cria e gerencia objetos flyweight. Garante que os flyweights serão compartilhados adequadamente. Quando um flyweight é requerido, o objeto FlyweightFactory fornece uma instância existente ao invés de criar uma nova, se nenuma existir. Client : Mantém referência para o(s) flyweight(s). Calcula ou guarda o estado extrínseco do(s) flyweight(s) Conseqüências: Flyweights podem introduzir custos em tempo de execução associados com transferir, buscar e ou computar o estado extrínseco. Apeasr disso, os custos são compensados pela economia de espaço, que cresce conforme mais objetos flyweights são compartilhados. A economia de espaço é função de vários fatores: a redução do número total de instâncias que vêm com o compartilhamento a quantidade de estados intrínsecos por objeto 30
40 3.7 Proxy Motivação: O padrão Proxy provê uma referência para um objeto com o objetivo de controlar o acesso a este.[5] O padrão Proxy é utilizado quando um sistema quer utilizar um objeto real, mas por algum motivo ele não está disponível. A solução então é providenciar um substituto que possa se comunicar com esse objeto quando ele estiver disponível. O cliente passa a usar o intermediário em vez do objeto real. O intermediário possui uma referencia para o objeto real e repassa as informações do cliente, filtrando dados e acrescentando informações Aplicabilidade: Remote Proxy - provê um representate local para um objeto em um espaço de endereçamento diferente. Virtual Proxy - cria objeto sob demanda. Protection Proxy - controla acesso ao objeto original. Smart References - executa operações adicionais quando o objeto é acessado Contagem de referências, carga de objetos persistentes, locks. Copy-on-write - compartilhar grandes objetos, fazendo uma cópia apenas se necessário. [9] enumera vantagens e desvantagens de padrão. 31