SlideShare ist ein Scribd-Unternehmen logo
1 von 63
Downloaden Sie, um offline zu lesen
PÓS-GRADUAÇÃO EM ANÁLISE E GESTÃO DE SISTEMAS DE INFORMAÇÃO
DÁVISSON HÚDSON CHAVES BERNADETE
EDUARDO COELHO CARNEIRO
FILIPE ARANTES FERNANDES
PADRÕES DE PROJETO (DESIGN PATTERNS)
Trabalho da Disciplina de Reutilização de Software
Campos do Goytacazes, RJ
2013
RESUMO
Padrões de projeto são padrões que visam estruturar soluções para problemas antes
encontrados em projetos de software, facilitando assim a criação de novos projetos já
que apresentam soluções eficazes para problemas conhecidos. Padrões de projetos não
são de fácil aplicação quando não se domina os conceitos que envolvem orientação a
objetos, porém tornam-se de grande ajuda para desenvolvedores e projetistas mais
experientes, facilitando bastante o trabalho. Padrões de projetos podem ser classificados
de forma geral como de criação, estrutural e comportamental, cada tipo atua de forma
diferente no tratamento dos objetos e classes. Padrões de projetos tendem a maximizar a
qualidade do projeto, tornando-os mais flexíveis e possibilitando um melhor reuso de
código. Os padrões de projeto mais conhecidos e utilizados são os 23 padrões do grupo
conhecido como GoF (Gang of Four), e com base principal no trabalho deles, o presente
trabalho aborda os padrões Abstract Factory, Decorator, Composite, Chain of
Responsibility, Observer, Strategy, Template Method e Visitor com exemplos de código
e explicações.
LISTA DE FIGURAS
Figura 1. Os 23 Padrões GoF (PEREIRA, 2013)............................................................................. 14
Figura 2. Estrutura do Padrão Abstract Factory (GAMMA et al., 2000)...................................... 18
Figura 3. Diagrama de classe fábrica de carros (BRIZENO, 2011) ............................................... 20
Figura 4. Estrutura padrão do Composite................................................................................... 23
Figura 5. Exemplo de implementação do padrão Composite..................................................... 24
Figura 6. Estrutura do padrão Decorator.................................................................................... 29
Figura 7. Exemplo de implementação do padrão Decorator...................................................... 30
Figura 8. Estrutura do Chain of Responsability........................................................................... 34
Figura 9. Diagrama de classes do exemplo do padrão Chain of Responsability ......................... 37
Figura 10. Estrutura do padrão Observer (GAMMA et al, 2000). ............................................... 39
Figura 11. Diagrama de sequência entre um subject e dois observadores (GAMMA et al, 2000).
..................................................................................................................................................... 40
Figura 12. Diagrama de classes da estação meteorológica......................................................... 41
Figura 13. Estrutura do Padrão Strategy (GAMMA et al., 2000)................................................. 46
Figura 14. Diagrama de classe do exemplo do padrão Visitor.................................................... 50
Figura 15. Diagrama de sequência do padrão Visitor ................................................................. 53
Figura 16. Diagrama de classes do exemplo de Visitor............................................................... 54
LISTA DE BLOCOS
Bloco 1. Interface FabricaDeCarro .............................................................................................. 20
Bloco 2. Classe FabricaFiat .......................................................................................................... 20
Bloco 3. Interfaces CarroPopular e CarroSedan.......................................................................... 21
Bloco 4. Implementação das interfaces CarroPopular e CarroSedan......................................... 21
Bloco 5. Classe de teste da Fábrica de Carros............................................................................. 22
Bloco 6. Implementação da classe MenuComponent................................................................ 25
Bloco 7. Implementação da classe MenuItem............................................................................ 26
Bloco 8. Implementação da classe Waitress............................................................................... 26
Bloco 9. Implementação da classe MenuItem............................................................................ 27
Bloco 10. Implementação da classe MenuTestDrive .................................................................. 28
Bloco 11. Implementação da classe Beverage............................................................................ 31
Bloco 12. Implementação das classes dos condimentos ............................................................ 32
Bloco 13. Implementação da classe StarbuzzCoffee................................................................... 33
Bloco 14. Implementação da enumeração de IDBancos ............................................................ 34
Bloco 15. Implementação da classe BancoChain........................................................................ 35
Bloco 16. Implementação do banco concreto ............................................................................ 36
Bloco 17. Implemantação do padrão Chain of Responsability ................................................... 36
Bloco 18. Interfaces Subject, Observer e DisplayElement .......................................................... 42
Bloco 19. Classe WeatherData.................................................................................................... 43
Bloco 20. Implemnetação das interfaces Observer e DisplayElement em
CurrentConditionDisplay............................................................................................................. 44
Bloco 21. Criação do objeto weatherData e as 3 exibições ........................................................ 44
Bloco 22. Interface CalculaImposto ............................................................................................ 47
Bloco 23. Implementaação do imposto de 20% ou 15%............................................................. 48
Bloco 24. Método construtor de Funcionario............................................................................. 48
Bloco 25. Classe Usuario. ............................................................................................................ 50
Bloco 26. Classe AbstractLogin.................................................................................................... 51
Bloco 27. Classes LoginPorArquivo e LoginPorBD....................................................................... 52
Bloco 28. Interfaces Visitable e Visitor........................................................................................ 55
Bloco 29. Classe abstrata Place................................................................................................... 55
Bloco 30. Implementação de Visitable na classe City. ................................................................ 55
Bloco 31. Classes Museum e Park............................................................................................... 56
Bloco 32. Classe FirstTimeVisitor. ............................................................................................... 57
Bloco 33. Classe JobSeekerVisitor............................................................................................... 57
Sumário
1. INTRODUÇÃO .................................................................................................................... 7
1.1. MOTIVAÇÃO E JUSTIFICATIVA............................................................................. 7
1.2. OBJETIVOS ................................................................................................................. 8
1.3. ORGANIZAÇÃO DO TRABALHO............................................................................ 8
2. REFERENCIAL TEÓRICO ................................................................................................. 9
2.1. REUTILIZAÇÃO.......................................................................................................... 9
2.2. ENCAPSULAMENTO................................................................................................. 9
2.3. HERANÇA, COMPOSIÇÃO, POLIMORFISMO E INTERFACE........................... 10
2.4. MANUTENIBILIDADE E GRANULARIDADE...................................................... 11
3. PADRÕES DE PROJETO (DESIGN PATTERNS)........................................................... 12
3.1. PADRÕES DE CRIAÇÃO ......................................................................................... 14
3.2. PADRÕES ESTRUTURAIS....................................................................................... 15
3.3. PADRÕES COMPORTAMENTAIS.......................................................................... 16
4. DESCREVENDO E EXEMPLIFICANDO ALGUNS PADRÕES.................................... 17
4.1. ABSTRACT FACTORY ............................................................................................ 17
4.1.1. Exemplo de Abstract Factory .............................................................................. 19
4.2. COMPOSITE .............................................................................................................. 22
4.2.1. Exemplo do Composite........................................................................................... 24
4.3. DECORATOR ............................................................................................................ 29
4.3.1. Exemplo do Decorator ........................................................................................ 30
4.4. CHAIN OF RESPONSIBILITY................................................................................. 33
4.4.1. Exemplo do Chain of Responsability ................................................................... 34
4.5. OBSERVER................................................................................................................ 37
4.5.1. Exemplo de Observer.......................................................................................... 41
4.6. STRATEGY................................................................................................................ 45
4.6.1. Exemplo de padrão Strategy............................................................................... 47
4.7. TEMPLATE METHOD.............................................................................................. 49
4.7.1. Exemplo do Template Method............................................................................ 49
4.8. VISITOR..................................................................................................................... 53
4.8.1. Exemplo de Visitor .............................................................................................. 54
5. PADRÕES NÃO GOF........................................................................................................ 58
5.1. SOA DESIGN PATTERNS........................................................................................ 58
6. CONCLUSÕES................................................................................................................... 59
6.1. CONTRIBUIÇÕES..................................................................................................... 59
6.2. LIMITAÇÕES............................................................................................................. 60
REFERÊNCIAS BIBLIOGRÁFICAS........................................................................................ 61
7
1. INTRODUÇÃO
Padrões de projeto podem ser vistos como uma solução que já foi testada para
um problema, ou seja, geralmente descreve uma solução ou uma instância da solução
que foi utilizada para resolver um problema específico. Padrões de projetos são
soluções para problemas que alguém um dia teve e resolveu aplicando um modelo que
foi documentado e adaptado integralmente ou de acordo com a necessidade de uma
solução (MACORATTI, 2002).
Um padrão de projeto deve auxiliar e prever alterações de um projeto. Segundo
Freeman et al. (2004), alteração é a única coisa com a qual podemos contar sempre no
desenvolvimento de software, independentemente de como seja desenvolvido um
aplicativo, com o tempo ele precisa crescer e mudar para não morrer.
Os padrões de projeto nos dizem como resolver alguns problemas, porém não
dizem como adaptar esses projetos para adequá-los aos aplicativos, pois eles estão num
nível acima das bibliotecas (FREEMAN et al., 2004). Além disso, fornecem uma
linguagem compartilhada que pode maximizar o valor da comunicação entre
desenvolvedores.
1.1. MOTIVAÇÃO E JUSTIFICATIVA
Frequentemente desenvolvedores deparam-se com problemas que já foram
resolvidos em projetos anteriores, com isso surgiu a necessidade de se criar padrões
como uma ajuda na resolução de problemas baseados em soluções que já funcionavam
em projetos já desenvolvidos. Assim, o agrupamento dessas soluções tende a ajudar na
construção de projetos melhores e com maior manutenibilidade e granularidade.
8
1.2. OBJETIVOS
Este trabalho visa explorar os conceitos de Padrões de Projeto, bem como
apresentar exemplos de alguns padrões escolhidos. Este trabalho se baseia nos padrões
de Gamma et al. (2000), porém também são apresentados alguns padrões de projeto
diferentes da abordagem principal, não se restringindo necessariamente a uma única
linha de pesquisa.
1.3. ORGANIZAÇÃO DO TRABALHO
De forma geral o trabalho apresenta mais cinco capítulos além desta
introdução, conforme descrito a seguir.
No capítulo 2, é apresentado um referencial teórico, onde observa-se os
conceitos de reutilização de software, encapsulamento, herança, composição,
polimorfismo, interface, manutenibilidade e granularidade. Esses conceitos estão
presentes de forma intrínseca em um projeto de Padrão de Projetos e por isso ganharam
espaço no referencial teórico.
O capítulo 3 aborda de forma mais profunda questões sobre design patterns, o
que são e para que servem, as principais propriedades dos padrões de projeto,
apresentará os prós e os contras de se implantar um padrão de projeto em determinados
projetos, os componentes principais de um padrão de projeto, requisitos de um bom
sistema de padrões, e como se utilizar padrões de projeto.
No capítulo 4 alguns padrões foram escolhidos para exemplificar o estudo de
Design Patterns realizado, os exemplos foram feitos em Java na maior parte.
Alguns padrões não desenvolvidos ou agrupados por Gamma et al são
apresentados no capítulo 5, porém sem muita ênfase, apenas a título de informação.
No capítulo 6, e último, são apresentadas algumas conclusões obtidas durante o
desenvolvimento do trabalho.
9
2. REFERENCIAL TEÓRICO
2.1. REUTILIZAÇÃO
A Reutilização é uma atividade já realizada há muito tempo por
desenvolvedores e projetistas de software. Embora a mesma seja feita de uma maneira
ad hoc, ideias, objetos, argumentos e abstrações sempre foram reutilizados por
desenvolvedores de software (PRESSMAN, 2006).
A reutilização pode ser definida como o processo de criação de sistemas a
partir de software preexistente (KRUEGER, 1992), trazendo consigo a promessa de
aumentar a produtividade e diminuir custos de desenvolvimento, além de melhorar a
qualidade do produto, através de artefatos de software já testados e utilizados em outros
contextos (FRAKES e KANG, 2005).
A reutilização de software não é uma técnica nova, ela surgiu no final dos anos
60, porém, anteriormente, se reutilizava apenas bibliotecas de rotinas ou partes de
código em ambientes de programação, mas com a orientação a objeto (OO) passou-se a
utilizar as classes para encapsular dados e funções, aumentando a granularidade
(ODYSSEY, 2007). A reutilização representa uma subárea da Engenharia de Software,
esta busca melhorar a qualidade dos artefatos de software e diminuir o tempo e esforços
necessários para produzi-los, assim como a intenção da reutilização.
Em uma organização o desenvolvimento pode ser para ou com reutilização,
dependendo do interesse. O desenvolvimento de software para reutilização tem como
fim produzir os artefatos para que sejam reutilizados futuramente, e no desenvolvimento
de software com reutilização, artefatos são incorporados ao sistema (BERNADETE et
al., 2007).
2.2. ENCAPSULAMENTO
Encapsular, de forma geral, significa esconder os dados, ou seja, não deixar
campos expostos para serem manipulados diretamente a partir de código externo, o que
lavaria a violações da invariante de representação ou a dependências indesejáveis que
10
impedem a alteração da implementação (MACORATTI, 2002). Segundo Macoratti
(2002) devemos esconder alguns componentes, permitindo apenas acessos estilizados
ao objeto, porém o acesso indireto pode reduzir o desempenho.
O encapsulamento serve para controlar o acesso aos atributos e métodos de
uma classe, e também é uma forma eficiente de proteger os dados manipulados dentro
da classe, além de determinar onde esta classe poderá ser manipulada (LEMOS, 2013).
Então para ter um método encapsulado utilizamos um modificador de acesso que
geralmente é público, além do tipo de retorno dele (LEMOS, 2013).
Encapsular é fundamental para que o sistema seja suscetível a mudanças, assim
não é preciso mudar uma regra de negócio em vários lugares, mas sim em apenas um
único lugar, já que a regra está encapsulada (CAELUM, 2011).
2.3. HERANÇA, COMPOSIÇÃO, POLIMORFISMO E INTERFACE
As duas maneiras mais comuns para reutilização de funcionalidades em
sistemas orientados a objetos são herança de classe e composição de objetos, a herança
de classe permite definir a implementação de uma classe em termos da implementação
de outra, já a composição por objetos é uma alternativa á herança onde a nova
funcionalidade é obtida pela montagem ou composição de objetos para obter
funcionalidades mais complexas (GAMMA et al., 2000).
A herança é um mecanismo da Orientação a Objeto que permite criar novas
classes a partir de classes já existentes, aproveitando-se das características existentes na
classe a ser estendida (LEMOS, 2013). Com herança é possível criar classes derivadas,
subclasses e superclasses. Herança pode ser associada com o termo “é um”.
Composição estende uma classe e delega o trabalho para o objeto desta classe,
onde uma instância da classe existente é usada como componente da outra classe
(MACORATTI, 2011). Composição pode ser associada com o termo “tem um”.
Usando composição os objetos que foram instanciados e estão contidos na
classe que os instanciou são acessados somente através de sua interface, além disso,
uma composição deve ser definida dinamicamente em tempo de execução pela obtenção
de referência de objetos a objetos do mesmo tipo e apresenta uma menor dependência
de implementações (MACORATTI, 2011).
11
Uma interface nada mais é do que um bloco de código definindo um tipo e os
métodos e atributos que esse tipo deve possuir. Na prática o que acontece é que
qualquer classe que quiser ser do tipo definido pela interface deve implementar os
métodos dessa interface (LEMOS, 2013). Segundo a Caelum (2011), uma interface
pode ser vista como um “contrato”, onde quem assinar esse contrato é obrigado, nesse
caso, a implementar os métodos da interface, não se herda métodos e atributos, mas sim
responsabilidades. Uma interface pode herdar de mais de uma interface, o que pode nos
levar a um melhor uso do polimorfismo.
Polimorfismo é o princípio pelo qual duas ou mais classes derivadas de uma
mesma superclasse podem invocar métodos que têm a mesma identificação, assinatura,
mas comportamentos distintos, especializados para cada classe derivada (LEMOS,
2013). Polimorfismo é a capacidade de um objeto poder ser referenciado de várias
formas, porém isso não significa que o objeto fica se transformando, pelo contrário, um
objeto nasce de um tipo e morre do mesmo tipo, o que pode mudar é a maneira como
nos referimos a ele (CAELUM, 2011).
É sempre bom programar pensando na interface da classe, como seus usuários
a estarão utilizando, e não somente em como ela irá funcionar (GAMMA et al, 2000).
2.4. MANUTENIBILIDADE E GRANULARIDADE
Manutenibilidade é uma das características de qualidade de software,
determinando o grau de facilidade com que o mesmo pode ser corrigido ou
aperfeiçoado, assim um software com alto índice de manutenibilidade necessita de
menos tempo e pessoas para ser modificado (BRUSAMOLIN, 2004).
Manutenibilidade de software diz respeito à facilidade com que o mesmo pode
ser modificado para satisfazer requisitos do usuário ou ser corrigido quando deficiências
são detectadas (PIGOSKI, 1996).
Granularidade diz respeito ao nível de detalhamento da classe ou objeto, assim
quanto mais granular for um software, mais partes menores ele vai ter. Um sistema
granular tem um número maior de objetos com tarefas mais específicas, ao passo que
um sistema menos granular possui poucas classes, porém classes maiores, com mais
funcionalidades por exemplo.
12
Granularidade demais impacta no processamento e dificulta o
desenvolvimento, porém granularidade a menos deixa o código com pouca
manutenibilidade e menos coeso.
3. PADRÕES DE PROJETO (DESIGN PATTERNS)
Segundo Macoratti (2002), padrões para arquitetura de software são soluções
de eficiência já comprovadas e amplamente utilizadas para a resolução de problemas
comuns em projeto de software, que são desenvolvidas e conhecidas por especialistas e
tornam-se padrões por serem reutilizadas várias vezes em vários projetos, tendo eficácia
comprovada.
Padrões de projeto são descrições de objetos e classes comunicantes que
precisam ser personalizadas para resolver um problema geral de projeto num contexto
particular (GAMMA et al., 2000).
É importante observar que um padrão de projeto deve nomear, abstrair e
identificar os aspectos que dão base a uma estrutura de projeto comum para torná-la
reutilizável, focalizando um problema ou particularidade do projeto orientado a objetos.
A utilização de padrões possibilita uma maior coesão e minimização da
complexidade e do acoplamento entre os elementos que integram a aplicação
(PEREIRA, 2008).
Com um padrão de projeto é mais fácil reutilizar projetos e arquiteturas bem-
sucedidas, porém, somente devem ser considerados projetos que foram aplicados mais
de uma vez em diferentes sistemas, pois é necessário comprovar a eficiência e a eficácia
da solução para ser considerado um padrão de projeto, assim nenhum padrão de projeto
descreve projetos novos ou não testados.
Conhecer conceitos como abstração, herança e polimorfismo são importantes,
mas não suficientes para ser um bom projetista, é necessário criar projetos flexíveis que
sejam fáceis de manter e modificar (FREEMAN et al., 2004).
Segundo Gamma et al. (2000), um padrão tem quatro elementos essenciais:
nome, problema, solução e consequências. Eles descrevem esses elementos da seguinte
forma: o nome do padrão é uma referência que deve descrever um problema de projeto,
suas soluções e consequências em uma ou duas palavras; o problema descreve em que
13
situação aplicar o padrão, deve explicar o problema e seu contexto; a solução descreve
os elementos que compõem o padrão de projeto, seus relacionamentos, suas
responsabilidades e colaborações, o padrão fornece uma descrição abstrata de um
problema de projeto e como um arranjo geral de elementos o resolve; as consequências
são os resultados e análises das vantagens e desvantagens da aplicação do padrão.
Dentre as principais propriedades dos padrões de projetos podemos citar que
capturam o conhecimento e a experiência de especialistas em projetos de software,
auxiliam o projeto de arquiteturas mais complexas (MACORATTI, 2002), especificam
abstrações que estão acima do nível de classes ou objetos isolados ou de componentes e
definem um vocabulário comum para discussão de problemas e soluções de projeto
(GAMMA et al., 2000), facilitam a documentação e manutenção da arquitetura do
software e também auxiliam o projeto de uma arquitetura com determinadas
propriedades (BUSCHMANN et al., 1996).
Como benefícios da utilização de padrões podemos destacar, segundo
Macoratti (2002):
• Fornecem soluções que já foram testadas e aprovadas.
• Tornam o sistema mais fácil de entender e manter.
• Facilitam o desenvolvimento de módulos coesos.
• A comunicação entre os participantes do projeto fica mais eficiente.
Como desvantagens pode-se citar o aumento da complexidade de entendimento
se não houver grande conhecimento de conceitos OO por parte dos envolvidos, e
também por adicionar acessos indiretos ou ao aumentar a quantidade de código, contudo
podem aumentar a capacidade de compreensão ao melhorar a modularidade, separando
melhor os conceitos e simplificando a descrição (UNIVERSIA).
Os requisitos para um bom sistema de padrões segundo Macoratti (2002): o
sistema deve conter uma boa quantidade de padrões; a descrição do padrão de seguir um
formato padronizado; o sistema deve ser estruturado; o sistema deve mostrar o
relacionamento entre os padrões e sua estrutura deve permitir evolução.
Para se utilizar padrões devemos ter bom senso, não adianta sair
implementando padrões sem ter certeza do porque utilizá-los, então o melhor é
implementar a solução e verificar se ela funciona para assim poder refatorá-la com os
padrões identificados para a melhoria e correção das deficiências do projeto.
14
Os padrões criados por Gamma et al. (2000) são os mais conhecidos
atualmente, e de acordo com eles os padrões podem ser de 3 tipos: padrões de criação,
estruturais e comportamentais. A figura 1 mostra a divisão dos padrões.
Figura 1. Os 23 Padrões GoF (PEREIRA, 2013)
3.1. PADRÕES DE CRIAÇÃO
Os padrões de criação abstraem o processo de instanciação, ajudam a tornar um
sistema independente de como seus objetos são criados, compostos e representados
(GAMMA et al., 2000).
Todos os padrões de criação encapsulam conhecimento sobre quais classes
concretas são usadas pelo sistema, e todas ocultam o modo como as instâncias destas
classes são criadas e compostas, a única coisa que o sistema sabe é que suas classes são
definidas por classes abstratas (GAMMA et al., 2000). Porém um padrão de criação dá
muita flexibilidade ao que, como e quando é criado e a quem cria (GAMMA et al.,
2000).
Uma descrição geral dos padrões de criação é apresentada a seguir.
Abstract Factory – Fornece uma interface para criação de famílias de objetos
relacionadas ou dependentes sem especificar suas classes concretas.
Builder – Separa a construção de um objeto complexo da sua representação, de
forma que o mesmo processo de construção possa criar diferentes representações.
15
Factory Method – Define uma interface para instanciação de objetos, mas deixa
as subclasses decidirem qual classe deve ser instanciada.
Prototype – Especifica os tipos de objetos a serem criados usando uma
instância prototípica e cria novos objetos copiando esse protótipo.
Singleton – Garante que para uma classe específica só possa existir uma única
instância, fornecendo um ponto global de acesso para ela.
3.2. PADRÕES ESTRUTURAIS
Os padrões estruturais se preocupam com a forma como classes e objetos são
compostos para formar estruturas maiores, eles utilizam herança para compor interfaces
ou implementações (GAMMA et al., 2000). Este tipo de padrão é bastante útil para
fazer bibliotecas de classes independentes trabalharem juntas.
Nesse padrão os padrões estruturais de objetos descrevem maneiras de compor
objetos para obter novas funcionalidades, assim a flexibilidade obtida pela composição
de objetos provém da capacidade de mudar a composição em tempo de execução
(GAMMA et al., 2000).
Uma descrição geral dos padrões estruturais é apresentada a seguir.
Adapter – Converte a interface de uma classe em outra interface esperada pelos
clientes. Permite que dois objetos se comuniquem mesmo que tenham interfaces
incompatíveis.
Bridge – Separa uma abstração de sua implementação, de forma que as duas
possam variar independentemente. Oculta detalhes de implementação dos clientes.
Composite – Permite que os clientes tratem objetos individuais e composições
de objetos de maneira uniforme. Ele lida com uma estrutura de elementos agrupada
hierarquicamente.
Decorator – Atribui responsabilidades adicionais a um objeto dinamicamente.
Ele fornece uma alternativa flexível a subclasses para a extensão da funcionalidade.
Facade – Fornece uma interface unificada para u conjunto de interfaces em um
subsistema, tornando o subsistema mais fácil de usar.
Flyweight – Usa compartilhamento para dar suporte a vários objetos de forma
eficiente.
16
Proxy – Fornece um objeto representante ou procurador de outro objeto para
controlar o acesso ao mesmo.
3.3. PADRÕES COMPORTAMENTAIS
Este tipo de padrão se preocupa com algoritmos e a atribuição de
responsabilidade entre objetos, eles não descrevem somente padrões de objetos ou
classes, mas também os padrões de comunicação entre eles, contudo, caracterizam
fluxos de controle difíceis de seguir em tempo de execução (GAMMA et al., 2000).
Padrões comportamentais de classe utilizam herança para distribuir o
comportamento entre as classes enquanto os padrões comportamentais de objetos
utilizam composição de objetos (GAMMA et al., 2000).
Uma descrição geral dos padrões comportamentais é apresentada a seguir.
Chain of Responsibility – Evita dependência do remetente (cliente) de uma
requisição ao seu destinatário, dando a oportunidade de mais de um objeto tratar a
requisição. Ele encadeia os objetos receptores e passa a solicitação ao longo da cadeia
até que um objeto a trate.
Command – Encapsula uma solicitação como um objeto, permitindo
parametrizar clientes com diferentes solicitações, enfileirar ou registrar solicitações e
suportar operações que podem ser desfeitas.
Interpreter – Dada uma linguagem, define-se uma representação para sua
gramática juntamente com um interpretador que usa a representação para interpretar
sentenças nessa linguagem.
Iterator – Provê uma forma de percorrermos os elementos de uma coleção sem
violar o seu encapsulamento.
Mediator – Cria um objeto que age como um mediador controlando a interação
entre um conjunto de objetos, ou seja, encapsula a forma como um conjunto de objetos
interage.
Memento – Torna possível salvar o estado de um objeto de modo que o mesmo
possa ser restaurado, sem violar o encapsulamento.
Observer – Define uma relação de dependência 1:N de forma que quando um
certo objeto (assunto) tem seu estado modificado os demais (observadores) são
17
notificados e atualizados. Possibilita baixo acoplamento entre os objetos observadores e
o assunto.
State – Permite a um objeto alterar seu comportamento quando estado interno
muda.
Strategy – Define uma família de algoritmos, encapsula cada um deles e os
torna intercambiáveis. Permite que o algoritmo varie independentemente dos clientes
que o utilizam.
Template Method – Define o esqueleto de um algoritmo em uma operação
adiando a definição de alguns passos para as subclasses. Ele permite que as subclasses
redefinam certos passos de um algoritmo sem mudar a sua estrutura.
Visitor – Define operações independentes a serem realizadas sobre elementos
de uma estrutura.
4. DESCREVENDO E EXEMPLIFICANDO ALGUNS PADRÕES
Este capítulo apresenta alguns padrões escolhidos para exemplificar o estudo
de Design Patterns realizado. Os exemplos são exibidos em Java e/ou Python.
4.1. ABSTRACT FACTORY
Criar objetos é mais do que simplesmente usar o operador new, criar instâncias
nem sempre deve ser feito de forma pública, isso pode gerar problemas de ligação
(FREEMAN et al., 2004). Os padrões Factory podem ajudar nessa situação. As
factories (fábricas) cuidam dos detalhes da criação dos objetos.
Segundo Gamma et al. (2000), o padrão Abstract Factory, também conhecido
como kit, fornece uma interface para criação de famílias de objetos relacionados ou
dependentes sem especificar suas classes concretas.
Abstract Factory permite que um cliente use uma interface abstrata para criar
um conjunto de produtos relacionados se saber, ou importar-se, sobre os produtos
concretos que são realmente produzidos, assim o cliente é desvinculado de qualquer
especificação dos produtos concretos (FREEMAN
Segundo Gamma et al
• Um sistema deve ser independente de como seus produtos
compostos ou representados;
• Um sistema deve ser configurado como um produto de uma família de
múltiplos produtos;
• Uma família de objetos
conjunto, e for necessário garantir essa restrição;
• Intende-se fo
revelar-se somente suas interfaces, não suas implementações.
Baseado em Gamma
Figura 2. Estrutura do Padrão Abstract
Assim temos os participantes de acordo
compilação de Gamma et al
• AbstractFactory
objetos-produto abstratos
concretas devem implementar, o que consiste em um conjunto de
métodos para fabricar produtos;
• Concrete Factory
concretos.
que são realmente produzidos, assim o cliente é desvinculado de qualquer
especificação dos produtos concretos (FREEMAN et al., 2004).
et al. (2000), este padrão deve ser aplicado quando:
Um sistema deve ser independente de como seus produtos
compostos ou representados;
Um sistema deve ser configurado como um produto de uma família de
múltiplos produtos;
Uma família de objetos-produto for projetada para ser usada em
conjunto, e for necessário garantir essa restrição;
se fornecer uma biblioteca de classes de produtos e quer
se somente suas interfaces, não suas implementações.
Baseado em Gamma et al. (2000) a estrutura do padrão é apresentada a seguir:
. Estrutura do Padrão Abstract Factory (GAMMA et al., 2000)
Assim temos os participantes de acordo da figura 2 explicitados segundo uma
et al. (2000) e Freeman et al. (2004):
Factory – Declara uma interface para operações que criam
produto abstratos. Define a interface que todas as fábricas
concretas devem implementar, o que consiste em um conjunto de
métodos para fabricar produtos;
Concrete Factory – Implementa as operações que criam objetos
As fábricas concretas implementam as diferentes famílias de
18
que são realmente produzidos, assim o cliente é desvinculado de qualquer
. (2000), este padrão deve ser aplicado quando:
Um sistema deve ser independente de como seus produtos são criados,
Um sistema deve ser configurado como um produto de uma família de
produto for projetada para ser usada em
rnecer uma biblioteca de classes de produtos e quer
se somente suas interfaces, não suas implementações.
. (2000) a estrutura do padrão é apresentada a seguir:
explicitados segundo uma
Declara uma interface para operações que criam
. Define a interface que todas as fábricas
concretas devem implementar, o que consiste em um conjunto de
mplementa as operações que criam objetos-produto
ferentes famílias de
19
produtos, e para criar um produto o cliente usa uma dessas fábricas,
assim nunca precisa criar a instância do objeto de um produto;
• AbstractProduct – Declara uma interface para um tipo de objeto-
produto. É a família de produtos onde cada fábrica concreta pode
produzir um conjunto inteiro de produtos;
• ConcreteProduct – Define um objeto-produto a ser criado pela
correspondente fábrica concreta. Também implementa a interface de
Abstract Product.
• Client – Usa somente interfaces declaradas pelas classes Abstract
Factory e Abstract Product. Em suma, é escrita para a Abstract Factory
e, depois, composta no tempo de execução com a Abstract Product.
Uma única instância de uma classe ConcreteFactory é criada em tempo de
execução normalmente. Para criar diferentes objetos-produto, os clientes deveriam usar
fábricas concretas diferentes (GAMMA et al., 2000).
Segundo Freeman et al. (2000), geralmente os métodos de uma Abstract
Factory são implementados como Factory Methods. O trabalho de uma Abstract Factory
é definir uma interface para criar um conjunto de produtos, e cada método nessa
interface é responsável pela criação de um produto concreto, assim implementamos uma
subclasse da Abstract Factory para fornecer essas implementações, dessa forma
percebe-se que os Factory Methods são uma forma natural de implementar métodos
concretos nas Abstract Factory.
As classes Abstract Factory são frequentemente implementadas com Factory
Methods, mas elas também podem ser implementadas usando Prototype, além disso,
uma fábrica concreta é frequentemente um Singleton (GAMMA et al., 2000).
As consequências de se usar esse padrão são apontadas por Gamma et al.
(2000): Isolamento das classes concretas; fácil troca de famílias de produtos; promove
harmonia entre produtos; difícil de suportar novos tipos de produtos.
4.1.1. Exemplo de Abstract Factory
Para Abstract Factory utilizou-se o exemplo de Brizeno (2011), que consiste na
representação de um sistema que, dado um conjunto de carros devemos manipulá-los.
Deve ser feito um agrupamento dos carros em conjuntos, de forma a agrupar objetos
que tenham comportamentos parecidos.
Para exemplificar os objetos foram organizados da seguinte forma:
Sedan (Siena – Fiat
Popular (Palio – Fiat
Assim o que deve ser feito é agrupar
conjunto de carros Popular para cada uma das fábricas.
do projeto de fábricas de carros Sedan e Popular.
Figura 3. Diagrama de c
O bloco 1 mostra uma interface para criação de Factories. Cada fábrica cria um
objeto de cada tipo, nesse caso um método para carros Sedan e outro para carros
Populares.
public class FabricaFiat
@Override
public CarroSedan criarCarroSedan() {
return new Siena();
}
@Override
public CarroPopular criarCarroPopular(
return new Palio();
}
public interface FabricaDeCarro {
CarroSedan criarCarroSedan();
CarroPopular criarCarroPopular();
}
agrupamento dos carros em conjuntos, de forma a agrupar objetos
que tenham comportamentos parecidos.
Para exemplificar os objetos foram organizados da seguinte forma:
Fiat, Fiesta Sedan – Ford);
Fiat, Fiesta – Ford).
o que deve ser feito é agrupar um conjunto de carros S
conjunto de carros Popular para cada uma das fábricas. A figura 3 apresenta a estrutura
do projeto de fábricas de carros Sedan e Popular.
. Diagrama de classe fábrica de carros (BRIZENO, 2011)
mostra uma interface para criação de Factories. Cada fábrica cria um
objeto de cada tipo, nesse caso um método para carros Sedan e outro para carros
FabricaFiat implements FabricaDeCarro {
CarroSedan criarCarroSedan() {
Siena();
CarroPopular criarCarroPopular() {
Palio();
FabricaDeCarro {
CarroSedan criarCarroSedan();
CarroPopular criarCarroPopular();
Bloco 1. Interface FabricaDeCarro
Bloco 2. Classe FabricaFiat
20
agrupamento dos carros em conjuntos, de forma a agrupar objetos
Para exemplificar os objetos foram organizados da seguinte forma:
um conjunto de carros Sedan e outro
apresenta a estrutura
mostra uma interface para criação de Factories. Cada fábrica cria um
objeto de cada tipo, nesse caso um método para carros Sedan e outro para carros
21
O bloco 2 cria os carros de fato, instanciando-os.
Todas as outras fábricas necessitam implementar a interface FabricaDeCarro.
A seguir a criação de mais duas interfaces:
Os dois métodos apresentados nas interfaces do bloco 3 exibem as informações
de seus tipos de carro, e apesar dos métodos executarem a mesma operação poderíamos
supor que os carros populares estão em um banco de dados e os sedans em outro, assim
cada método precisa criar sua própria conexão.
O bloco 4 apresenta os produtos concretos implementando suas interfaces.
public class Palio implements CarroPopular {
@Override
public void exibirInfoPopular() {
System.out.println("Modelo: PalionFábrica: FiatnCategoria:Popular");
}
}
public class Siena implements CarroSedan {
@Override
public void exibirInfoSedan() {
System.out.println("Modelo: SienanFábrica: FiatnCategoria:Sedan");
}
}
public interface CarroPopular {
void exibirInfoPopular();
}
public interface CarroSedan {
void exibirInfoSedan();
}
Bloco 3. Interfaces CarroPopular e CarroSedan
Bloco 4. Implementação das interfaces CarroPopular e CarroSedan
22
Analisando o bloco 5 percebe-se que foi criada uma fábrica abstrata e foi
colocado nela qualquer fábrica, de acordo com a necessidade, e de forma semelhante foi
criada referências para um carro Popular e para um carro Sedan, e ainda de acordo com
nossas necessidades foram sendo utilizados os carros dos fabricantes.
Segundo Brizeno (2011) com esse padrão criamos uma estrutura muito grande
de classes e interfaces para resolver o problema de criação de objetos, porém baseado
no princípio da Segregação de Interface isto é uma coisa boa, pois o código cliente fica
dependendo de interfaces simples e pequenas ao invés de depender de uma interface
grande e que nem todos os métodos seriam utilizados.
4.2. COMPOSITE
O Composite é um tipo de padrão estrutural e tem como objetivo permitir a
composição de objetos em estruturas de árvore para representar hierarquias parte-todo
possibilitando o tratamento de objetos individuais ou composições de objetos de modo
uniforme.
Segundo Gamma et al. (2000), Composite deve tratar objetos primitivos e
objetos recipientes de modo diferente, mesmo se na maior parte do tempo o usuário os
trata de forma idêntica. Ter que distinguir entre esses objetos torna a aplicação mais
complexa. O padrão Composite descreve como usar a composição recursiva de maneira
que os clientes não tenham que fazer essa distinção.
public static void main(String[] args) {
FabricaDeCarro fabrica = new FabricaFiat();
CarroSedan sedan = fabrica.criarCarroSedan();
CarroPopular popular = fabrica.criarCarroPopular();
sedan.exibirInfoSedan();
System.out.println();
popular.exibirInfoPopular();
System.out.println();
fabrica = new FabricaFord();
sedan = fabrica.criarCarroSedan();
popular = fabrica.criarCarroPopular();
sedan.exibirInfoSedan();
System.out.println();
popular.exibirInfoPopular();
}
Bloco 5. Classe de teste da Fábrica de Carros
O segredo do padrão é a
representa tanto as primitivas
operações que todos os objetos compostos compartilham, tais como operações para
acessar e manipular seus filhos.
demonstrada na Figura 4,
para filhos e composições.
Será de fácil compreensão se olharmos a estrutura como uma árvore de cabeça
para baixo. Um nó pode ter filhos e também um nó que, por sua vez, pode ter outros
filhos e nós. Neste padrão,
sendo declaradas em Component
classe só deve ter uma responsabilidade, no qual o padrão
De acordo com Freeman (2004)
Responsabilidade Única e o troca pela transparência. O fato de o cliente lidar
uniformemente com os compostos e os nó
Contudo, como as operações estão sendo declaradas na classe
pouco de segurança, pois um cliente pode tentar fazer algo inadequado ou sem sentido
com um elemento. Isto é decisão de projeto; pode
direção, separando as responsabilidades em diferentes interfaces. Isto tornaria o projeto
seguro, no sentido de que quaisquer chamadas inadequadas de elementos seriam
detectadas por ocasião da compilação ou da execução. Poré
transparência, e o código necessitaria de usar condicionais e o operador
Portanto, esse é um típico caso de que se perde algo para obter algum benefício.
Um projetista deve ser guiado pelos princípios de projeto, mas deve f
no efeito que eles têm sobre os projetos. Alguma modelagem pode parecer desrespeitar
O segredo do padrão é a recursividade devido a uma classe abstrata que
representa tanto as primitivas como os seus recipientes. Esta classe abstrata declara
operações que todos os objetos compostos compartilham, tais como operações para
acessar e manipular seus filhos. Por exemplo, observando a estrutura padrão
, a classe Component declara métodos que são utilizados só
para filhos e composições.
Figura 4. Estrutura padrão do Composite
Será de fácil compreensão se olharmos a estrutura como uma árvore de cabeça
o. Um nó pode ter filhos e também um nó que, por sua vez, pode ter outros
, nota-se que Leaf herda operações de Composite
Component. Segundo princípios de orientação a objetos, uma
uma responsabilidade, no qual o padrão Composite não respeita.
De acordo com Freeman (2004), o padrão abre mão do princípio de projetos da
Responsabilidade Única e o troca pela transparência. O fato de o cliente lidar
com os compostos e os nós-folha é caracterizado transparência.
Contudo, como as operações estão sendo declaradas na classe Component
pouco de segurança, pois um cliente pode tentar fazer algo inadequado ou sem sentido
com um elemento. Isto é decisão de projeto; pode-se conduzir o processo em outra
direção, separando as responsabilidades em diferentes interfaces. Isto tornaria o projeto
seguro, no sentido de que quaisquer chamadas inadequadas de elementos seriam
detectadas por ocasião da compilação ou da execução. Porém, poderia perder a
transparência, e o código necessitaria de usar condicionais e o operador
Portanto, esse é um típico caso de que se perde algo para obter algum benefício.
deve ser guiado pelos princípios de projeto, mas deve ficar atento sempre
no efeito que eles têm sobre os projetos. Alguma modelagem pode parecer desrespeitar
23
uma classe abstrata que
como os seus recipientes. Esta classe abstrata declara
operações que todos os objetos compostos compartilham, tais como operações para
observando a estrutura padrão
declara métodos que são utilizados só
Será de fácil compreensão se olharmos a estrutura como uma árvore de cabeça
o. Um nó pode ter filhos e também um nó que, por sua vez, pode ter outros
Composite que estão
Segundo princípios de orientação a objetos, uma
não respeita.
o padrão abre mão do princípio de projetos da
Responsabilidade Única e o troca pela transparência. O fato de o cliente lidar
é caracterizado transparência.
Component, perde-se um
pouco de segurança, pois um cliente pode tentar fazer algo inadequado ou sem sentido
se conduzir o processo em outra
direção, separando as responsabilidades em diferentes interfaces. Isto tornaria o projeto
seguro, no sentido de que quaisquer chamadas inadequadas de elementos seriam
m, poderia perder a
transparência, e o código necessitaria de usar condicionais e o operador instanceof.
Portanto, esse é um típico caso de que se perde algo para obter algum benefício.
icar atento sempre
no efeito que eles têm sobre os projetos. Alguma modelagem pode parecer desrespeitar
algum princípio, porém, tudo é uma questão de perspectiva. De acordo com Freeman
(2004), talvez pareça incorreto ter operações de gerenciamento de filho
mas pode-se deslocar um pouco a perspectiva e ver uma folha como um nó com zero
filhos.
4.2.1. Exemplo do Composite
Para implementar este tipo de padrão, é
(2004) demonstrado na Figura
Figura 5
De forma resumida, a classe
na composição; implementa comportamento
classes, conforme apropriado; declara uma interface para acessar e gerenciar os seus
componentes-filhos e defin
estrutura recursiva e a implementa. Em
composição (um item de menu
menu em menu. Na classe
filhos; armazena os itens de menu e implementa as operações relacionadas com os
filhos presentes na interface de
os objetos na composição através da interface de
algum princípio, porém, tudo é uma questão de perspectiva. De acordo com Freeman
(2004), talvez pareça incorreto ter operações de gerenciamento de filho
se deslocar um pouco a perspectiva e ver uma folha como um nó com zero
Exemplo do Composite
mentar este tipo de padrão, é abordado um exemplo de Freeman
Figura 5.
5. Exemplo de implementação do padrão Composite
De forma resumida, a classe MenuComponent declara a interface para os objetos
na composição; implementa comportamento-padrão para a interface comum a todas a
classes, conforme apropriado; declara uma interface para acessar e gerenciar os seus
define uma interface para acessar o pai de um componente na
estrutura recursiva e a implementa. Em MenuItem, representa objetos
um item de menu não tem filhos) e define comportamento para
Na classe Menu, define comportamento para componentes que têm
itens de menu e implementa as operações relacionadas com os
ce de MenuComponent. E Waitress é a classe que manipula
os objetos na composição através da interface de MenuComponent.
24
algum princípio, porém, tudo é uma questão de perspectiva. De acordo com Freeman
(2004), talvez pareça incorreto ter operações de gerenciamento de filhos nos nós-folha,
se deslocar um pouco a perspectiva e ver uma folha como um nó com zero
abordado um exemplo de Freeman
declara a interface para os objetos
padrão para a interface comum a todas as
classes, conforme apropriado; declara uma interface para acessar e gerenciar os seus
uma interface para acessar o pai de um componente na
objetos-folha na
comportamento para os itens do
, define comportamento para componentes que têm
itens de menu e implementa as operações relacionadas com os
é a classe que manipula
25
A implementação da classe MenuComponent é demonstrada no Bloco 6. É
nítido que esta classe só estabelece o contrato das operações deixando a cargo de suas
sub-classes a implementação de cada operação que lhe interessa.
Bloco 6. Implementação da classe MenuComponent
Em MenuItem, é implementado as operações que dizem respeito aos itens de
menu, ou seja, não é possível implementar a operação add, pois não faz sentido um item
de menu ter um filho, demonstrado no Bloco 7.
As operações referentes a um menu, são implementadas na classe Menu,
apresentada no Bloco 9. Menu é do tipo MenuComponent e que, por sua vez, pode ter
qualquer quantidade de filhos do tipo MenuComponents. Com a herança mais
composição é possível ter a recursividade desejada.
Tanto em MenuItem quanto Menu, possuem as mesmas operações, como por
exemplo print. Em MenuItem, basta somente imprimir o nome, se é um tipo de comida
vegetariana, o preço e a descrição. Já em Menu, a operação print deverá imprimir seu
public abstract class MenuComponent{
public void add(MenuComponent menuComponent){
throw new UnsupportedOperationException();
}
public void remove(MenuComponent menuComponent){
throw new UnsupportedOperationException();
}
public MenuComponent getChild(int i){
throw new UnsupportedOperationException();
}
public String getName(){
throw new UnsupportedOperationException();
}
public String getDescription(){
throw new UnsupportedOperationException();
}
public double getPrice(){
throw new UnsupportedOperationException();
}
public boolean isVegetarian(){
throw new UnsupportedOperationException();
}
public void print(){
throw new UnsupportedOperationException();
}
}
26
nome, descrição e o print implementado em MenuItem. Para que isso seja feito, foi
implementado o padrão Iterator. Ele busca todos os métodos print dos objetos do tipo
MenuComponent e executa.
Bloco 7. Implementação da classe MenuItem
A classe que interage com esta estrutura é Waitress e está apresentada no Bloco
8. Ela simplesmente executa o método print.
Bloco 8. Implementação da classe Waitress
public class Waitress{
MenuComponent allMenus;
public Waitress(MenuComponent allMenus){
this.allMenus = allMenus;
}
public void printMenu(){
allMenus.print();
}
}
public class MenuItem extends MenuComponent{
String name; String description; boolean vegetarian; double price;
public MenuItem(String name, String description, boolean vegetarian, double
price){
this.name = name; this.description = description; this.vegetarian =
vegetarian; this.price = price;
}
public String getName(){
return name;
}
public String getDescription(){
return description;
}
public double getPrice(){
return price;
}
public boolean isVegetarian(){
return vegetarian;
}
public void print(){
System.out.print(" "+getName());
if(isVegetarian()){
System.out.print("(v)");
}
System.out.println(", "+getPrice());
System.out.println(" -- "+getDescription());
}
}
27
Bloco 9. Implementação da classe MenuItem
E por fim, a classe MenuTestDrive mostra um exemplo de como criar um menu
raiz e acrescentar seus menus, itens e as recursividades, caso necessário. Veja no Bloco
10. São criados os menus e também o menu raiz denominado allMenus, este objeto
representa toda a estrutura hierarquizada. Ao objeto allMenus, são adicionados outros
menus, sendo que estes menus serão adicionados itens e, no caso abaixo, o menu
dinerMenu possui um sub-menu dessertMenu, e que este possui um item nomeado
Apple Pie. Para exibir toda a estrutura é chamado o método print de Waitress.
public class MenuItem extends MenuComponent{
import java.util.ArrayList;
import java.util.Iterator;
public class Menu extends MenuComponent{
ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>();
String name; String description;
public Menu(String name, String description){
this.name = name; this.description = description;
}
public void add(MenuComponent menuComponent){
menuComponents.add(menuComponent);
}
public void remove(MenuComponent menuComponent){
menuComponents.remove(menuComponent);
}
public MenuComponent getChild(int i){
return (MenuComponent)menuComponents.get(i);
}
public String getName(){
return name;
}
public String getDescription(){
return description;
}
public void print(){
System.out.print("n"+getName());
System.out.println(", "+getDescription());
System.out.println("---------------------");
Iterator iterator = menuComponents.iterator();
while(iterator.hasNext()){
MenuComponent menuComponent = (MenuComponent)iterator.next();
menuComponent.print();
}
}
}
28
Bloco 10. Implementação da classe MenuTestDrive
Gamma et al.(2000) faz algumas considerações sobre este padrão.
• Hierarquias que consistem de objetos primitivos e compostos. Os
primitivos podem compor objetos mais complexos, os quais, por suas
vez, também podem compor outros objetos, e assim por diante
recursivamente. Sempre que o código esperar um objeto primitivo, ele
também poderá aceitar um objeto composto.
• Torna o cliente simples. Os clientes podem tratar estruturas compostas e
objetos individuas de maneira uniforme. Os clientes normalmente não
sabem (e não sabem deveriam se preocupar com isto) se estão tratando
com uma folha ou um componente composto. Isto simplifica o código a
ser escrito nas classes-cliente, porque evita o uso de comandos do tipo
CASE com os rótulos classes que definem composição.
• Torna mais fácil de acrescentar novas espécies de componentes. Novas
subclasses definidas, Composite ou Leaf, funcionam automaticamente
com as estruturas existentes e o código do cliente. Os clientes não
precisam ser alterados para tratar novas classes Component.
• Pode tornar o projeto excessivamente genérico. A desvantagem de
facilitar o acréscimo de novos componentes é que isso torna mais difícil
restringir os componentes de uma composição. Algumas vezes, é
public class MenuTestDrive{
public static void main(String args[]){
MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU","Breakfast");
MenuComponent dinerMenu = new Menu("DINER MENU","Lunch");
MenuComponent cafeMenu = new Menu("CAFÉ MENU","Dinner");
MenuComponent dessertMenu = new Menu("DESSERT MENU","Dessert of course!");
MenuComponent allMenus = new Menu("ALL MENUS","All menus combined");
allMenus.add(pancakeHouseMenu);
allMenus.add(dinerMenu);
allMenus.add(cafeMenu);
dinerMenu.add(new MenuItem("Pasta","Spaghetti with Marinara Sauce, and a slice
of sourdough bread",true,3.89));
dinerMenu.add(dessertMenu);
dessertMenu.add(new MenuItem("Apple Pie","Apple pie with a flakey crust,
topped with vanilla ice cream",true,1.59));
Waitress waitress = new Waitress(allMenus);
waitress.printMenu();
}
}
desejável que uma composição tenha somente certos componentes. Com
Composite, não pode confiar no sistema de tipos para garantir a
obediência a essas restrições. Ao invés disso, deve
teste em tempo d
4.3. DECORATOR
Este padrão, de forma dinâmica, agrega valores adicionais em qualquer objeto.
Fornece alternativa flexível no uso de subclasses para estender funcionalidades.
De acordo com Gamma
responsabilidades a objetos individuais dinamicamente e sem afetar outros objetos.
Outra característica é que essas responsabilidades pode
de alguma forma, desempenho ou estrutura.
Decorar objetos é muito comum quando não se quer te
subclasses. Por exemplo, havendo a necessidade de combinar responsabilidades entre
classes em um total de 6, i
diferentes.
Segundo Freeman (2004), q
subclasses, este comportament
Todas as subclasses devem herdar o mesmo comportamento. Contudo, por meio da
composição será possível esten
tempo de execução.
O padrão segue a seguinte
desejável que uma composição tenha somente certos componentes. Com
, não pode confiar no sistema de tipos para garantir a
obediência a essas restrições. Ao invés disso, deve-se usar verificações e
teste em tempo de execução.
DECORATOR
Este padrão, de forma dinâmica, agrega valores adicionais em qualquer objeto.
Fornece alternativa flexível no uso de subclasses para estender funcionalidades.
Gamma et al. (2000), o uso do Decorator acrescenta
bilidades a objetos individuais dinamicamente e sem afetar outros objetos.
Outra característica é que essas responsabilidades podem ser removidas sem prejudicar,
de alguma forma, desempenho ou estrutura.
Decorar objetos é muito comum quando não se quer ter uma explosão de
subclasses. Por exemplo, havendo a necessidade de combinar responsabilidades entre
classes em um total de 6, isso acarretará numa explosão de 40 combinações
Segundo Freeman (2004), quando há herança de um comportamento por meio de
subclasses, este comportamento é definido estaticamente no tempo de compilação.
Todas as subclasses devem herdar o mesmo comportamento. Contudo, por meio da
composição será possível estender o comportamento do objeto de forma dinâmica
seguinte estrutura:
Figura 6. Estrutura do padrão Decorator
29
desejável que uma composição tenha somente certos componentes. Com
, não pode confiar no sistema de tipos para garantir a
se usar verificações e
Este padrão, de forma dinâmica, agrega valores adicionais em qualquer objeto.
Fornece alternativa flexível no uso de subclasses para estender funcionalidades.
uso do Decorator acrescenta
bilidades a objetos individuais dinamicamente e sem afetar outros objetos.
ser removidas sem prejudicar,
r uma explosão de
subclasses. Por exemplo, havendo a necessidade de combinar responsabilidades entre 3
combinações de classes
amento por meio de
é definido estaticamente no tempo de compilação.
Todas as subclasses devem herdar o mesmo comportamento. Contudo, por meio da
forma dinâmica e em
A classe Component
responsabilidades acresce
define um objeto para o qual responsabilidades adicionais podem ser atribuídas; a classe
Decorator mantém uma referência para um objeto
que segue a interface de Component
ao componente.
4.3.1. Exemplo do Decorator
Freeman (2004) apresenta
mostrado na figura 5.
Beverage é uma classe abstrata de componente.
sozinha ou englobada por um decorador.
componentes concretos que
são um tipo de bebida. Esses objetos
CondimentDecorator “tem
CondimentDecorator tem uma variável de instância que co
bebida. Mocha, Whip e Soy
Beverage. Os decoradores podem adicionar novos métodos; no entanto, o novo
comportamento geralmente é adicionado fazendo cálculo antes e depois de um método
existente no componente. Eles precisam implementar não somente
getDescription().
Figura 7
Component define a interface para objetos que podem ter
ntadas aos mesmos dinamicamente; Concre
define um objeto para o qual responsabilidades adicionais podem ser atribuídas; a classe
mantém uma referência para um objeto Component e define uma interface
Component e ConcreteDecorator acrescenta responsabi
Exemplo do Decorator
apresenta um exemplo de aplicação do padrão decorator
é uma classe abstrata de componente. Cada bebida
por um decorador. Expresso, DarkRoast e HouseBlend
componentes concretos que estendem de Beverage no que caracteriza que essas classes
Esses objetos receberão dinamicamente novos comportamentos.
“tem-uma” (engloba) uma bebida, o que si
tem uma variável de instância que contém uma referência a uma
Soy são os decoradores e eles pode estender o estado de
es podem adicionar novos métodos; no entanto, o novo
mento geralmente é adicionado fazendo cálculo antes e depois de um método
Eles precisam implementar não somente cost()
7. Exemplo de implementação do padrão Decorator
30
define a interface para objetos que podem ter
ConcretComponent
define um objeto para o qual responsabilidades adicionais podem ser atribuídas; a classe
e define uma interface
acrescenta responsabilidades
padrão decorator
pode ser usada
HouseBlend são
no que caracteriza que essas classes
receberão dinamicamente novos comportamentos.
” (engloba) uma bebida, o que significa que o
ntém uma referência a uma
são os decoradores e eles pode estender o estado de
es podem adicionar novos métodos; no entanto, o novo
mento geralmente é adicionado fazendo cálculo antes e depois de um método
cost(), mas também
31
No bloco abaixo, segue o código para implementação da classe Beverage e suas
subclasses.
Bloco 11. Implementação da classe Beverage
A classe CondimentDecorator simplesmente repassa as solicitações de
descrições para a bebida e suas subclasses estendem essa operação. O código é
mostrado no bloco abaixo.
public abstract class Beverage{
String description = "Unknown Beverage";
public String getDescription(){
return description;
}
public abstract double cost();
}
public class Expresso extends Beverage{
public Expresso(){
description = "Expresso";
}
public double cost(){
return 1.99;
}
}
public class HouseBlend extends Beverage{
public HouseBlend(){
description = "House Blend Coffee";
}
public double cost(){
return 0.89;
}
}
public class DarkRoast extends
Beverage{
public DarkRoast(){
description = "Dark Roast";
}
public double cost(){
return 1.05;
}
}
32
Bloco 12. Implementação das classes dos condimentos
Com o padrão Decorator tornam-se fácil acrescentar os condimentos as bebidas
de forma dinâmica. Assim, não é preciso estabelecer que cada bebida possa ter apenas
um condimento, ou combinações de dois. Por exemplo, Expresso pode ter o condimento
Whip e também Whip com Soy ou até os três. Com uma pequena quantidade pode
public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();
}
public class Soy extends CondimentDecorator{
Beverage beverage;
public Soy(Beverage beverage){
this.beverage = beverage;
}
public String getDescription(){
return beverage.getDescription()+ ", Soy";
}
public double cost(){
return 0.15 + beverage.cost();
}
}
public class Whip extends CondimentDecorator{
Beverage beverage;
public Whip(Beverage beverage){
this.beverage = beverage;
}
public String getDescription(){
return beverage.getDescription()+", Whip";
}
public double cost(){
return 0.10 + beverage.cost();
}
}
public class Mocha extends CondimentDecorator{
Beverage beverage;
public Mocha(Beverage beverage){
this.beverage = beverage;
}
public String getDescription(){
return beverage.getDescription() + ", Mocha";
}
public double cost(){
return 0.20 + beverage.cost();
}
}
33
parecer fácil, mas se tivesse 20 condimentos para 10 tipos de bebidas ficaria difícil de
criar cada classe representando uma bebida com combinações de condimentos.
A atribuição de comportamentos em tempo de execução é apresentada no
seguinte bloco.
Bloco 13. Implementação da classe StarbuzzCoffee
No objeto beverage é simplesmente instanciado o objeto Expresso sem nenhum
condimento. Seu preço final será de R$ 1.99. Em beverage2, é instanciado o objeto
DarkRoast e é acrescentado 3 tipos de condimentos: Mocha, Soy e Whip. Para que
beverage2 contenha os condimentos é preciso instanciá-los e passar o tipo da bebida
como parâmetro, formando uma espécie de invólucro. Mocha envolve beverage2, assim
como Soy e Whip da mesma forma. A descrição da bebida retornará “Dark Roast,
Mocha, Soy, Whip” e o preço final (somando o custo da bebida mais os condimentos)
de R$ 1,50. De igual modo beverage3 recebe um condimento e a descrição e o preço
são alterados.
4.4. CHAIN OF RESPONSIBILITY
O Chain of Responsability (Cadeia de Responsabilidades) é um tipo de padrão
comportamental e, segundo Gamma et al. (2000), a intenção do padrão é evitar o
acoplamento do remetente de uma solicitação ao seu receptor, ao dar a mais de um
objeto a oportunidade de tratar a solicitação. Encadear os objetos receptores, passando a
solicitação ao longo da cadeia até que um objeto a trate. Na Figura 8 está demonstrada a
public class StarbuzzCoffee{
public static void main(String args[]){
Beverage beverage = new Expresso();
System.out.println(beverage.getDescription()+" R$"+beverage.cost());
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);
beverage2 = new Soy(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription()+" R$"+beverage2.cost());
Beverage beverage3 = new HouseBlend();
beverage3 = new Mocha(beverage3);
System.out.println(beverage3.getDescription()+" R$"+beverage3.cost());
}
}
estrutura básica do padrão. A class
e opcionalmente implementa o elo (
solicitações pelas quais é responsável podendo também acessar seu sucessor e se o
ConcreteHandler pode tratar a
solicitação para o seu sucessor. Por fim, a classe
objeto ConcreteHandler da cadeia, (GAMMA et al., 2000).
O efeito que se dá quando um cliente emite uma solic
longo da cadeia até que um objeto
la.
Figura
4.4.1. Exemplo do Chain of Responsability
Para exemplificar, é abordado
uma operação efetuar pagamento entre os bancos.
Para iniciar, criar-
sistema, exibido no Bloco 14
Bloco
A classe BancoChain
responsabilidades. Ela possui um atributo que é o ident
referência para o próximo objeto. O método
e faz verifica se o próximo for nulo, então o próximo na corrente será o parâmetro; caso
public enum IDBancos {
bancoA, bancoB, bancoC, bancoD
}
drão. A class Handler define uma interface para tratar solicitações
e opcionalmente implementa o elo (link) ao sucessor. ConcreteHandle
solicitações pelas quais é responsável podendo também acessar seu sucessor e se o
pode tratar a solicitação, ele assim o faz; caso contrário, ele repassa a
solicitação para o seu sucessor. Por fim, a classe Client inicia a solicitação para um
da cadeia, (GAMMA et al., 2000).
O efeito que se dá quando um cliente emite uma solicitação, esta se propaga ao
longo da cadeia até que um objeto ConcreteHandler assuma a responsabilidade de tratá
Figura 8. Estrutura do Chain of Responsability
Exemplo do Chain of Responsability
Para exemplificar, é abordado um exemplo de Brizeno (2011) que implementa
uma operação efetuar pagamento entre os bancos.
-se uma enumeração que identificará os bancos utilizado no
14.
Bloco 14. Implementação da enumeração de IDBancos
BancoChain , exibida no Bloco 15, implementará a cadeia de
responsabilidades. Ela possui um atributo que é o identificador do banco e outro a
referência para o próximo objeto. O método setNext recebe uma nova instância da classe
e faz verifica se o próximo for nulo, então o próximo na corrente será o parâmetro; caso
bancoA, bancoB, bancoC, bancoD
34
define uma interface para tratar solicitações
ConcreteHandle trata de
solicitações pelas quais é responsável podendo também acessar seu sucessor e se o
solicitação, ele assim o faz; caso contrário, ele repassa a
inicia a solicitação para um
itação, esta se propaga ao
assuma a responsabilidade de tratá-
um exemplo de Brizeno (2011) que implementa
que identificará os bancos utilizado no
implementará a cadeia de
ificador do banco e outro a
recebe uma nova instância da classe
e faz verifica se o próximo for nulo, então o próximo na corrente será o parâmetro; caso
35
contrário, repassa esta responsabilidade para o próximo elemento. Então, a instância que
deve ser adicionada na corrente irá percorrer os elementos até chegar ao último.
O algoritmo de pagamento é verificar se o banco atual pode fazer o pagamento.
Para isto é utilizado o identificador do banco, que é comparado com o identificador
passado por parâmetro. Se o elemento atual puder responder a requisição é chamado o
método que vai efetuar o pagamento de fato. Este método é abstrato, e as subclasses
devem implementá-lo, com seu próprio mecanismo.
Se o elemento atual não puder responder, ele repassa a chamado ao próximo
elemento da lista. Antes disto é feita uma verificação, por questões de segurança, se este
próximo elemento realmente existe. Caso nenhum elemento possa responder, é
disparada uma exceção.
Bloco 15. Implementação da classe BancoChain
public enum IDBancos {
public abstract class BancoChain {
protected BancoChain next;
protected IDBancos identificadorDoBanco;
public BancoChain(IDBancos id) {
next = null;
identificadorDoBanco = id;
}
public void setNext(BancoChain forma) {
if (next == null) {
next = forma;
} else {
next.setNext(forma);
}
}
public void efetuarPagamento(IDBancos id) throws Exception {
if (podeEfetuarPagamento(id)) {
efetuaPagamento();
} else {
if (next == null) {
throw new Exception("banco não cadastrado");
}
next.efetuarPagamento(id);
}
}
private boolean podeEfetuarPagamento(IDBancos id) {
if (identificadorDoBanco == id) {
return true;
}
return false;
}
protected abstract void efetuaPagamento();
}
36
Definida a estrutura da cadeia de responsabilidades, implementa-se um banco
concreto, que corresponde a uma chamada. O BancoA inicializa seu ID e, no método de
efetuar o pagamento, exibe no terminal que o pagamento foi efetuado. A implementação
dos ostros bancos segue este exemplo, exibida no Bloco 16 abaixo.
Bloco 16. Implementação do banco concreto
Sendo assim, cada banco chama seu método efetuarPagamento de acordo com a
cadeia de responsabilidades criada, de acordo com o bloco abaixo.
Bloco 17. Implemantação do padrão Chain of Responsability
O diagrama de classes deste exemplo mostrado na Figura 9.
public static void main(String[] args) {
BancoChain bancos = new BancoA();
bancos.setNext(new BancoB());
bancos.setNext(new BancoC());
bancos.setNext(new BancoD());
try {
bancos.efetuarPagamento(IDBancos.bancoC);
bancos.efetuarPagamento(IDBancos.bancoD);
bancos.efetuarPagamento(IDBancos.bancoA);
bancos.efetuarPagamento(IDBancos.bancoB);
} catch (Exception e) {
e.printStackTrace();
}
}
public class BancoA extends BancoChain {
public BancoA() {
super(IDBancos.bancoA);
}
@Override
protected void efetuaPagamento() {
System.out.println("Pagamento efetuado no banco A");
}
}
Figura 9. Diagrama de classes do exemplo do padrão Chain of Responsability
Gamma et al. (2000), dest
• Acoplamento reduzido
qual o outro objeto que trata de uma solicitação. Um objeto tem que
saber somente que uma solicitação será tratada "apropriadamente"
Tanto o receptor como o remetente não conhecimento explícito um do
outro, e um objeto que está na cadeia não necessita conhecer a estrutura
da mesma.
• Flexibilidade adicional na atribuição de responsabilidades a objetos
Chain of Responsability dá uma flex
responsabilidades entre objetos. É possível acrescentar ou mudar
responsabilidades para o tratamento de uma solicitação pelo acréscimo
ou mudança da cadeia em tempo de execução. Pode
com subclasses pa
• A recepção não é garantida
receptor explícito, não há
pode sair pelo final da cadeia sem ter sido tratada. Uma solicitação
também pode não ser tratada quando a cadeia não está configurada
apropriadamente.
4.5. OBSERVER
O padrão Observer
Subscribe, define uma dependência um
. Diagrama de classes do exemplo do padrão Chain of Responsability
Gamma et al. (2000), destaca alguns benefícios e deficiências deste padrão.
Acoplamento reduzido: o padrão libera um objeto de ter que conhecer
qual o outro objeto que trata de uma solicitação. Um objeto tem que
saber somente que uma solicitação será tratada "apropriadamente"
anto o receptor como o remetente não conhecimento explícito um do
outro, e um objeto que está na cadeia não necessita conhecer a estrutura
Flexibilidade adicional na atribuição de responsabilidades a objetos
Chain of Responsability dá uma flexibilidade adicional na distribuição de
responsabilidades entre objetos. É possível acrescentar ou mudar
responsabilidades para o tratamento de uma solicitação pelo acréscimo
ou mudança da cadeia em tempo de execução. Pode-se combinar isto
com subclasses para especializar estaticamente os handlers
A recepção não é garantida. Uma vez que uma solicitação não tem um
receptor explícito, não há garantia de que ela será tratada
pode sair pelo final da cadeia sem ter sido tratada. Uma solicitação
também pode não ser tratada quando a cadeia não está configurada
apropriadamente.
O padrão Observer, também conhecido como Dependents ou Publish
efine uma dependência um-para-muitos entre objetos de forma que quando
37
. Diagrama de classes do exemplo do padrão Chain of Responsability
aca alguns benefícios e deficiências deste padrão.
um objeto de ter que conhecer
qual o outro objeto que trata de uma solicitação. Um objeto tem que
saber somente que uma solicitação será tratada "apropriadamente" .
anto o receptor como o remetente não conhecimento explícito um do
outro, e um objeto que está na cadeia não necessita conhecer a estrutura
Flexibilidade adicional na atribuição de responsabilidades a objetos. O
ibilidade adicional na distribuição de
responsabilidades entre objetos. É possível acrescentar ou mudar
responsabilidades para o tratamento de uma solicitação pelo acréscimo
se combinar isto
handlers.
. Uma vez que uma solicitação não tem um
de que ela será tratada - a solicitação
pode sair pelo final da cadeia sem ter sido tratada. Uma solicitação
também pode não ser tratada quando a cadeia não está configurada
, também conhecido como Dependents ou Publish-
muitos entre objetos de forma que quando
38
um objeto mudar de estado, todos os seus dependentes sejam notificados e atualizados
automaticamente (GAMMA et al., 2000).
No Observer quando um estado de um objeto é alterado, todos os seus
dependentes são notificados, e dependendo do tipo de notificação o observador também
pode ser atualizado com novos valores (FREEMAN et al., 2004). Observer desacopla
um objeto do conhecimento de que outros objetos dependem dele (ROCHA, 2003).
Existem algumas maneiras diferentes de se implementar o padrão Observer,
mas a maioria inclui as interfaces Subject e Observer. Um subject pode ter um número
qualquer de observadores dependentes, e todos os observadores são notificados quando
subject sofre uma mudança de estado, assim em resposta, cada observador inquirirá o
subject para sincronizar o seu estado com o estado do subject (GAMMA et al., 2000).
Esta iteração é o que GAMMA et al. (2000) chama de publish-subscribe, onde o subject
é o publicador de notificações e as envia sem ter que saber quem são os seus
observadores, lembrando que um número qualquer de observadores podem se inscrever
para receber essas notificações, nota-se então que existe uma relação entre um subject e
muitos observadores (1:N).
Como o sujeito é o único proprietário dos dados, os observadores dependem do
sujeito para alterá-los quando os dados são alterados, o que leva a um design orientado a
objetos mais simples do que permitir que muitos objetos controlem os mesmos dados
(FREEMAN et al., 2004).
Segundo Gamma et al. (2000), este padrão deve ser aplicado:
• Quando uma abstração tem dois aspectos, um dependente do outro.
Encapsulam-se esses aspectos separadamente para que assim permita-se
variá-los e reutizá-los independentemente.
• Quando uma mudança em um objeto exige mudanças em outros
objetos, e não sabe-se quantos objetos necessitam ser mudados.
• Quando não deseja-se que objetos sejam fortemente acoplados.
O padrão Observer fornece um design de objeto onde os sujeitos e os
observadores são levemente ligados, ou seja, os objetos podem interagir, mas sabem
muito pouco um do outro, o que trona mais fácil lidar com mudanças, já que minimizam
a interdependência entre os objetos (FREEMAN et al., 2004). Isso porque a única coisa
que o sujeito sabe sobre um observador é que ele implementa uma certa interface
(Observer), com isso podemos adicionar novos observadores a qualquer momento,
nunca precisaremos modificar o sujeito para adicionar novos tipos de observadores e
ainda podemos reutilizar sujeitos ou observadores independentemente uns dos outros
(FREEMAN et al., 2004).
Segundo o Rocha
padrões centrada no padrão Observer
o View é o Observer para o
pelo usuário e lê dados
encapsulando lógica de controle que afeta o
A figura 10 mostra a estrutura do padrão Observer.
Figura 10
Os participantes dessa estrutura são explicitados segundo Gamma
e Freeman et al. (2004):
• Subject –
objetos Observer pode observar um subject. Os objetos usam esta
interface para se regi
removidos.
• Observer –
deveriam ser notificados sobre mudanças em um subject. Todos os
observadores potenciais precisam implementar essa interface.
demos adicionar novos observadores a qualquer momento,
nunca precisaremos modificar o sujeito para adicionar novos tipos de observadores e
ainda podemos reutilizar sujeitos ou observadores independentemente uns dos outros
(2003) o padrão de arquitetura MVC é uma combinação de
padrões centrada no padrão Observer, onde o Model notifica o View sobre as alterações;
é o Observer para o Model e notifica o Controller sobre os eventos iniciados
pelo usuário e lê dados do Model; e o Controller é um Observer para o
encapsulando lógica de controle que afeta o Model e seleciona View.
mostra a estrutura do padrão Observer.
. Estrutura do padrão Observer (GAMMA et al, 2000).
Os participantes dessa estrutura são explicitados segundo Gamma
conhece os seus observadores. Um número qualquer de
objetos Observer pode observar um subject. Os objetos usam esta
interface para se registrarem como observadores e para serem
removidos.
– define uma interface de atualização para objetos que
deveriam ser notificados sobre mudanças em um subject. Todos os
observadores potenciais precisam implementar essa interface.
39
demos adicionar novos observadores a qualquer momento,
nunca precisaremos modificar o sujeito para adicionar novos tipos de observadores e
ainda podemos reutilizar sujeitos ou observadores independentemente uns dos outros
padrão de arquitetura MVC é uma combinação de
sobre as alterações;
sobre os eventos iniciados
é um Observer para o View,
Os participantes dessa estrutura são explicitados segundo Gamma et al. (2000)
conhece os seus observadores. Um número qualquer de
objetos Observer pode observar um subject. Os objetos usam esta
strarem como observadores e para serem
define uma interface de atualização para objetos que
deveriam ser notificados sobre mudanças em um subject. Todos os
observadores potenciais precisam implementar essa interface.
• ConcreteSubject
ConcreteObserver. Envia uma notificação para os seus observadores
quando seu estado muda.
• ConcreteObserver
que implemente a interface Observer. Mantém uma referênc
objeto ConcreteSubject, também armazena estados que deveriam
permanecer consistentes com os do Subject. Implementa a interface de
atualização de Observer, para manter seu estado consistente com o do
subject.
O ConcreteSubject notifica seus obser
mudança que poderia tornar inconsistente o estado deles com o seu próprio
et al., 2000).
A figura 11 apresenta um diagrama de sequencia de como as colaborações
acontecem entre um subject e dois observadores.
Figura 11. Diagrama de sequência entre um subject e dois observadores (GAMMA et al, 2000).
O objeto Observer na figura xxx que inicia a solicitação de mudança posterga
sua atualização até que consiga uma notificação do subject. Notify nã
chamada pelo subject, pode ser chamada por um observador ou por um outro tipo de
objeto (GAMMA et al., 2000).
As conseqüências (benefícios e deficiências) da utilização desse padrão
apontadas por Gamma et al. (2000) são: permite acrescentar obse
modificar o subject ou outros observadores; permite variar subjects e observadores de
forma independente; acoplamento abstrato entre Subject e
ConcreteSubject – armazena estados de interesse para objetos
ConcreteObserver. Envia uma notificação para os seus observadores
quando seu estado muda.
ConcreteObserver – os ConcreteObservers podem ser qualquer classe
que implemente a interface Observer. Mantém uma referênc
objeto ConcreteSubject, também armazena estados que deveriam
permanecer consistentes com os do Subject. Implementa a interface de
atualização de Observer, para manter seu estado consistente com o do
O ConcreteSubject notifica seus observadores sempre que ocorrer uma
mudança que poderia tornar inconsistente o estado deles com o seu próprio
apresenta um diagrama de sequencia de como as colaborações
acontecem entre um subject e dois observadores.
. Diagrama de sequência entre um subject e dois observadores (GAMMA et al, 2000).
O objeto Observer na figura xxx que inicia a solicitação de mudança posterga
sua atualização até que consiga uma notificação do subject. Notify nã
chamada pelo subject, pode ser chamada por um observador ou por um outro tipo de
., 2000).
As conseqüências (benefícios e deficiências) da utilização desse padrão
apontadas por Gamma et al. (2000) são: permite acrescentar obse
modificar o subject ou outros observadores; permite variar subjects e observadores de
forma independente; acoplamento abstrato entre Subject e Observer, e por não serem
40
armazena estados de interesse para objetos
ConcreteObserver. Envia uma notificação para os seus observadores
os ConcreteObservers podem ser qualquer classe
que implemente a interface Observer. Mantém uma referência para um
objeto ConcreteSubject, também armazena estados que deveriam
permanecer consistentes com os do Subject. Implementa a interface de
atualização de Observer, para manter seu estado consistente com o do
vadores sempre que ocorrer uma
mudança que poderia tornar inconsistente o estado deles com o seu próprio (GAMMA
apresenta um diagrama de sequencia de como as colaborações
. Diagrama de sequência entre um subject e dois observadores (GAMMA et al, 2000).
O objeto Observer na figura xxx que inicia a solicitação de mudança posterga
sua atualização até que consiga uma notificação do subject. Notify não é sempre
chamada pelo subject, pode ser chamada por um observador ou por um outro tipo de
As conseqüências (benefícios e deficiências) da utilização desse padrão
apontadas por Gamma et al. (2000) são: permite acrescentar observadores sem
modificar o subject ou outros observadores; permite variar subjects e observadores de
Observer, e por não serem
fortemente acoplados os mesmos podem pertencer a diferentes camadas de abs
suporte a comunicações broadcast sem especificar seu receptor; atualizações
inesperadas, pois como um observador não conhece a presença dos outros, eles podem
ser cegos para o custo global de mudança.
Os padrões relacionados são Mediator, encapsula
atualizações complexas, onde o ChangeManager atua como um mediador entre subjects
e observadores, e o Singleton onde o ChangeManager pode usar o Singleton para torná
lo único e globalmente acessível.
4.5.1. Exemplo de Observer
Para exemplificar o padrão Observer
(2004), incluindo a base da explicação sobre o exemplo
construção de uma estação meteorológica baseada na Internet, que deverá monitorar as
condições atuais do tempo (te
aplicativo que forneça as condições atuais, estatísticas meteorológicas e uma simples
previsão. A figura 12 apresenta o diagrama de classes que será utilizado no exemplo
Figura
fortemente acoplados os mesmos podem pertencer a diferentes camadas de abs
suporte a comunicações broadcast sem especificar seu receptor; atualizações
inesperadas, pois como um observador não conhece a presença dos outros, eles podem
ser cegos para o custo global de mudança.
Os padrões relacionados são Mediator, encapsulando a semântica de
atualizações complexas, onde o ChangeManager atua como um mediador entre subjects
e observadores, e o Singleton onde o ChangeManager pode usar o Singleton para torná
lo único e globalmente acessível.
Exemplo de Observer
car o padrão Observer utilizou-se um exemplo de
, incluindo a base da explicação sobre o exemplo. O exemplo baseia
construção de uma estação meteorológica baseada na Internet, que deverá monitorar as
condições atuais do tempo (temperatura, umidade e pressão). A ideia é criar
que forneça as condições atuais, estatísticas meteorológicas e uma simples
apresenta o diagrama de classes que será utilizado no exemplo
Figura 12. Diagrama de classes da estação meteorológica
41
fortemente acoplados os mesmos podem pertencer a diferentes camadas de abstração;
suporte a comunicações broadcast sem especificar seu receptor; atualizações
inesperadas, pois como um observador não conhece a presença dos outros, eles podem
ndo a semântica de
atualizações complexas, onde o ChangeManager atua como um mediador entre subjects
e observadores, e o Singleton onde o ChangeManager pode usar o Singleton para torná-
um exemplo de Freeman et al.
O exemplo baseia-se na
construção de uma estação meteorológica baseada na Internet, que deverá monitorar as
mperatura, umidade e pressão). A ideia é criar um
que forneça as condições atuais, estatísticas meteorológicas e uma simples
apresenta o diagrama de classes que será utilizado no exemplo.
42
De acordo com o diagrama de classe todos os componentes meteorológicos
implementam a interface Observer, o que dá a Subject uma interface comum com a qual
falar na hora de atualizar os observadores, e a interface DisplayElement deve ser
implementada por todos os elementos de exibição. As interfaces utilizadas são
mostradas no bloco 18.
Na interface Subject temos um método para registro e outro para exclusão de
um elemento, que utilizam um Observer como argumento. A interface Observer possue
o método update recebe os valores de estado do Subject quando uma medição muda.
Essa interface é implementada por todos os observadores. A interface DisplayElement
possui apenas o método display() que é chamado quando o elemento de exibição
precisar ser exibido.
A classe WeatherData monitora os dados vindos de Estação Meteorológica e
atualiza as exibições. O objeto WeatherData sabe como falar com a estação e obter os
dados atualizados de temperatura, umidade de pressão. O método
measurementsChanged() é chamado sempre que dados de medição estão disponíveis.
O bloco 19 mostra a classe WeatherData. Essa classe implementa a interface
Subject e adiciona uma lista para conter os Observers no método construtor. Como
implementamos Subject, os métodos registerObserver(), removeObserver() e
notifyObservers() devem ser aplicados, assim para adicionar um observador ele é
colocado no final da lista e para remover ele é retirado da lista. No notifyObservers() é
onde passamos para todas os observadores sobre o estado. O método
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
public interface Observer {
public void update(float temp, float umidade, float pressao);
}
public interface DisplayElement {
public void display();
}
Bloco 18. Interfaces Subject, Observer e DisplayElement
43
measurementsChanged() notifica os Observers quando obtemos medições atualizadas da
Estação meteorológica. O método setMeasurements() foi utilizado para testar os
elementos de exibição.
Após isso, é hora de construir os elementos de exibição: exibição das
condições atuais, exibição das estatísticas e exibição da previsão. Todas as classes que
farão essas exibições devem implementar Observer e DisplayElement, nesse exemplo
public class WeatherData implements Subject{
private ArrayList observers;
private float temperatura;
private float umidade;
private float pressao;
public WeatherData(){
observers = new ArrayList();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if (i >= 0){
observers.remove(i);
}
}
@Override
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer) observers.get(i);
observer.update(temperatura, umidade, pressao);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperatura, float umidade, float pressao){
this.temperatura = temperatura;
this.umidade = umidade;
this.pressao = pressao;
measurementsChanged();
}
Bloco 19. Classe WeatherData
44
mostra-se apenas a implementação da exibição das condições atuais, pois as outras
seguem um formato parecido. O bloco 20 apresenta essa implementação.
A classe CurrentConditionsDisplay deve receber o objeto WeatherData (o
Subject) para registrar a exibição como um observador. O método display() imprimi
apenas a temperatura e a umidade mais recentes.
A classe de teste deverá criar o objeto WeatherData e as três exibições que
serão passadas para WeatherData, conforme bloco 21.
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new
CurrentConditionsDisplay(weatherData);
StatisticsDisplay statisticsDisplay = new
StatisticsDisplay(weatherData); //mostrar algumas estatísticas
ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
//previsão de acordo com a pressão
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperatura;
private float umidade;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData){
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void update(float temperatura, float umidade, float pressao) {
this.temperatura = temperatura;
this.umidade = umidade;
display();
}
@Override
public void display() {
System.out.println("Condições atuais: " + temperatura + "C graus e
" + umidade + "% umidade");
}
}
Bloco 20. Implemnetação das interfaces Observer e DisplayElement em CurrentConditionDisplay.
Bloco 21. Criação do objeto weatherData e as 3 exibições
45
Nesse exemplo criamos o um exemplo do padrão Observer, porém se
utilizarmos Java, há a opção de contar com o suporte interno ao padrão Observer dele,
assim tudo que teríamos que fazer é estender Observable e informá-lo quando notificar
os Observadores, pois a API faria o resto.
4.6. STRATEGY
O padrão Strategy, também conhecido como Policy, define uma família de
algoritmos, encapsula cada um deles e os torna intercambiáveis, assim a estratégia deixa
o algoritmo varias independentemente dos clientes que o utilizam (GAMMA et al.,
2000).
Strategy sugere que algoritmos parecidos sejam separados de quem os utiliza
(BRIZENO, 2011). Devemos separar o que muda do que fica igual (FREEMAN et al.,
2004). O padrão também apresenta facilidade para extensão das funcionalidades e
nenhuma outra parte do código precisa ser alterada. Nesse padrão as classes de
estratégia são chamadas de Comportamento e a classe que utiliza o comportamento é
chamada de Contexto, ou seja, para um determinado Contexto pode-se aplicar um
conjunto de comportamentos (BRIZENO, 2011).
Segundo Gamma et al. (2000), o padrão Strategy se aplica quando:
• Muitas classes relacionadas diferem somente no seu comportamento.
• Necessita-se de variantes de um algoritmo. As estratégias podem ser
usadas quando essas variantes são implementadas como uma hierarquia
de classes de algoritmos.
• Um algoritmo usa dados dos quais os clientes não deveriam ter
conhecimento.
• Uma classe define muitos comportamentos, e estes aparecem em suas
operações como múltiplos comandos condicionais da linguagem.
Strategy usa composição. Usar composição dá mais flexibilidade e permite
encapsular uma família de algoritmos em seu próprio conjunto de classes, além disso
permite alterar o comportamento no tempo de execução, desde o objeto com o qual
estiver compondo implemente a interface de comportamento certa (FREEMAN et al.,
2004). A composição é usada em outros padrões de projetos além do Strategy.
A figura 13 apresenta a estrutura do padrão Strategy.
Figura 13
Os participantes dessa estrutura são explicitados segundo Gamma
• Strategy –
suportados, e o Context usa esta interface para chamar o algoritmo
definido por uma ConcreteStrategy.
• ConcreteStrategy
Strategy.
• Context –
uma referência para um objeto Strategy. Pode definir uma interface que
permite a Strategy acessar seus dados.
Strategy e Context interagem para i
disso um contexto repassa solicitações dos seus clientes para sua estratégia (GAMMA
et al., 2000). A chave para aplicação do padrão Strategy é projetar, para a estratégia e
seu contexto, interfaces genéricas o bastant
(GAMMA et al., 2000).
Como consequências, entre benefícios e desvantagens, Gamma
aponta: famílias de algoritmos relacionadas; uma alternativa ao uso de subclasses;
eliminam comandos condicionais da l
escolha de implementações, fornecendo diferentes implementações do mesmo
comportamento; os clientes devem conhecer diferentes
podem ser expostos a detalhes e aspectos de implementação;
entre Strategy e Context pode ser um problema; aumento do número de objetos.
Quando outra pessoa está utilizando seu código ela pode escolher qualquer
comportamento para o contexto que ela deseja aplicar, o que
13. Estrutura do Padrão Strategy (GAMMA et al., 2000).
s dessa estrutura são explicitados segundo Gamma
– define uma interface comum para todos os algoritmos
suportados, e o Context usa esta interface para chamar o algoritmo
definido por uma ConcreteStrategy.
ConcreteStrategy – implementa o algoritmo usando a interface de
é configurado com um objeto ConcreteStrategy e mantém
uma referência para um objeto Strategy. Pode definir uma interface que
permite a Strategy acessar seus dados.
Strategy e Context interagem para implementar o algoritmo escolhido, além
disso um contexto repassa solicitações dos seus clientes para sua estratégia (GAMMA
A chave para aplicação do padrão Strategy é projetar, para a estratégia e
seu contexto, interfaces genéricas o bastante para suportar uma variedade de algoritmos
Como consequências, entre benefícios e desvantagens, Gamma
aponta: famílias de algoritmos relacionadas; uma alternativa ao uso de subclasses;
eliminam comandos condicionais da linguagem de programação; possibilidade de
escolha de implementações, fornecendo diferentes implementações do mesmo
comportamento; os clientes devem conhecer diferentes Strategies, assim os clientes
podem ser expostos a detalhes e aspectos de implementação; custo de comunicação
entre Strategy e Context pode ser um problema; aumento do número de objetos.
Quando outra pessoa está utilizando seu código ela pode escolher qualquer
contexto que ela deseja aplicar, o que pode ser visto como um
46
s dessa estrutura são explicitados segundo Gamma et al. (2000).
define uma interface comum para todos os algoritmos
suportados, e o Context usa esta interface para chamar o algoritmo
ta o algoritmo usando a interface de
é configurado com um objeto ConcreteStrategy e mantém
uma referência para um objeto Strategy. Pode definir uma interface que
mplementar o algoritmo escolhido, além
disso um contexto repassa solicitações dos seus clientes para sua estratégia (GAMMA
A chave para aplicação do padrão Strategy é projetar, para a estratégia e
e para suportar uma variedade de algoritmos
Como consequências, entre benefícios e desvantagens, Gamma et al (2000)
aponta: famílias de algoritmos relacionadas; uma alternativa ao uso de subclasses;
inguagem de programação; possibilidade de
escolha de implementações, fornecendo diferentes implementações do mesmo
, assim os clientes
custo de comunicação
entre Strategy e Context pode ser um problema; aumento do número de objetos.
Quando outra pessoa está utilizando seu código ela pode escolher qualquer
pode ser visto como um
47
potencial problema, já que o usuário deve conhecer bem a diferença entre as estratégias
para saber escolher qual se aplica melhor ao contexto dele (BRIZENO, 2011).
Como padrão relacionado temos o Flyweight, onde objetos Strategy geralmente
são bons flyweights (GAMMA et al., 2000).
4.6.1. Exemplo de padrão Strategy
Para exemplificar o padrão Strategy, utilizou-se um exemplo apresentado por
Brizeno (2011) com suas explicações, onde em uma empresa existe um conjunto de
cargos, para cada cargo existem regras de cálculo de imposto e determinada
porcentagem do salário deve ser retirada de acordo com o salário base do funcionário.
As regras são mostradas a seguir:
• O Desenvolvedor deve ter um imposto de 15% caso seu salário seja
maior que R$ 2000,00 e 10% caso contrário;
• O Gerente deve ter um imposto de 20% caso seu salário seja maior que
R$ 3500,00 e 15% caso contrário;
• O DBA deve ter um imposto de de 15% caso seu salário seja maior que
R$ 2000,00 e 10% caso contrário;
O padrão Strategy sugere que os métodos de cálculo de imposto sejam
separados do funcionário. Assim devemos encapsular todos os algoritmos da mesma
família, ou seja, a família que calcula salários com impostos deve ser separada, e para
encapsulá-las cria-se uma interface. O bloco 22 apresenta a criação da interface de
calculo do imposto.
Após definida a classe que encapsula os algoritmos, as estratégias concretas de
calculo do imposto devem ser definidas, assim como Brizeno (2011) definiremos
apenas uma das classes de cálculo, pois as outras 2 seguem o mesmo padrão. O Bloco
23 mostra a implementação do imposto de 20% ou 15%.
interface CalculaImposto {
double calculaSalarioComImposto(Funcionario umFuncionario);
}
Bloco 22. Interface CalculaImposto
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns
Padrões de Projeto - Design Patterns

Weitere ähnliche Inhalte

Was ist angesagt?

Coreldraw graphics suite_x5
Coreldraw graphics suite_x5Coreldraw graphics suite_x5
Coreldraw graphics suite_x5aulaemvideo
 
Padrões de projeto - Adapter, Proxy, Composite e Bridge
Padrões de projeto - Adapter, Proxy, Composite e BridgePadrões de projeto - Adapter, Proxy, Composite e Bridge
Padrões de projeto - Adapter, Proxy, Composite e BridgeLorran Pegoretti
 
De javaparapython
De javaparapythonDe javaparapython
De javaparapythonTiago
 
Planejamento em desenvolvimento_de_sistemas
Planejamento em desenvolvimento_de_sistemasPlanejamento em desenvolvimento_de_sistemas
Planejamento em desenvolvimento_de_sistemasTiago
 
Python gtk
Python gtkPython gtk
Python gtkTiago
 
Java applet
Java appletJava applet
Java appletTiago
 
Java awt
Java awtJava awt
Java awtTiago
 
50718286 apostila-de-asp-net-c-e-visual-basic-net
50718286 apostila-de-asp-net-c-e-visual-basic-net50718286 apostila-de-asp-net-c-e-visual-basic-net
50718286 apostila-de-asp-net-c-e-visual-basic-netThais Rodrigues
 
Desenvolvimento do protótipo de uma ferramenta para Engenharia de Requisitos ...
Desenvolvimento do protótipo de uma ferramenta para Engenharia de Requisitos ...Desenvolvimento do protótipo de uma ferramenta para Engenharia de Requisitos ...
Desenvolvimento do protótipo de uma ferramenta para Engenharia de Requisitos ...Diego Lusa
 
MODELAGEM E IMPLEMENTAÇÃO DE UM VISUALIZADOR PARA SIMULAÇÕES COMPUTACIONAIS D...
MODELAGEM E IMPLEMENTAÇÃO DE UM VISUALIZADOR PARA SIMULAÇÕES COMPUTACIONAIS D...MODELAGEM E IMPLEMENTAÇÃO DE UM VISUALIZADOR PARA SIMULAÇÕES COMPUTACIONAIS D...
MODELAGEM E IMPLEMENTAÇÃO DE UM VISUALIZADOR PARA SIMULAÇÕES COMPUTACIONAIS D...Jesimar Arantes
 
Drupal
DrupalDrupal
DrupalTiago
 

Was ist angesagt? (20)

Manual corel draw
Manual corel drawManual corel draw
Manual corel draw
 
Coreldraw graphics suite_x5
Coreldraw graphics suite_x5Coreldraw graphics suite_x5
Coreldraw graphics suite_x5
 
Padrões de projeto - Adapter, Proxy, Composite e Bridge
Padrões de projeto - Adapter, Proxy, Composite e BridgePadrões de projeto - Adapter, Proxy, Composite e Bridge
Padrões de projeto - Adapter, Proxy, Composite e Bridge
 
Padrões de Projeto de Software
Padrões de Projeto de SoftwarePadrões de Projeto de Software
Padrões de Projeto de Software
 
Java Basico
Java BasicoJava Basico
Java Basico
 
Jspservlets
JspservletsJspservlets
Jspservlets
 
De javaparapython
De javaparapythonDe javaparapython
De javaparapython
 
Planejamento em desenvolvimento_de_sistemas
Planejamento em desenvolvimento_de_sistemasPlanejamento em desenvolvimento_de_sistemas
Planejamento em desenvolvimento_de_sistemas
 
Python gtk
Python gtkPython gtk
Python gtk
 
Java applet
Java appletJava applet
Java applet
 
Java awt
Java awtJava awt
Java awt
 
Inkscape
InkscapeInkscape
Inkscape
 
J2me
J2meJ2me
J2me
 
Gimp
GimpGimp
Gimp
 
50718286 apostila-de-asp-net-c-e-visual-basic-net
50718286 apostila-de-asp-net-c-e-visual-basic-net50718286 apostila-de-asp-net-c-e-visual-basic-net
50718286 apostila-de-asp-net-c-e-visual-basic-net
 
Zope
ZopeZope
Zope
 
Desenvolvimento do protótipo de uma ferramenta para Engenharia de Requisitos ...
Desenvolvimento do protótipo de uma ferramenta para Engenharia de Requisitos ...Desenvolvimento do protótipo de uma ferramenta para Engenharia de Requisitos ...
Desenvolvimento do protótipo de uma ferramenta para Engenharia de Requisitos ...
 
Jdbc
JdbcJdbc
Jdbc
 
MODELAGEM E IMPLEMENTAÇÃO DE UM VISUALIZADOR PARA SIMULAÇÕES COMPUTACIONAIS D...
MODELAGEM E IMPLEMENTAÇÃO DE UM VISUALIZADOR PARA SIMULAÇÕES COMPUTACIONAIS D...MODELAGEM E IMPLEMENTAÇÃO DE UM VISUALIZADOR PARA SIMULAÇÕES COMPUTACIONAIS D...
MODELAGEM E IMPLEMENTAÇÃO DE UM VISUALIZADOR PARA SIMULAÇÕES COMPUTACIONAIS D...
 
Drupal
DrupalDrupal
Drupal
 

Andere mochten auch

Padrões de Projeto - Observer e Strategy
Padrões de Projeto - Observer e StrategyPadrões de Projeto - Observer e Strategy
Padrões de Projeto - Observer e StrategyJoão Carlos Ottobboni
 
Padroes De Projeto
Padroes De ProjetoPadroes De Projeto
Padroes De Projetoejdn1
 
Exemplos de Design Patterns em Java
Exemplos de Design Patterns em JavaExemplos de Design Patterns em Java
Exemplos de Design Patterns em Javaalexmacedo
 
Padrões de Projeto J2EE para Aplicações Web
Padrões de Projeto J2EE para Aplicações WebPadrões de Projeto J2EE para Aplicações Web
Padrões de Projeto J2EE para Aplicações WebDenis L Presciliano
 
Introdução a Padrões de Projeto - Engenharia de Software
Introdução a Padrões de Projeto - Engenharia de SoftwareIntrodução a Padrões de Projeto - Engenharia de Software
Introdução a Padrões de Projeto - Engenharia de SoftwareWillian Carminato
 
Observer - Padrões de projeto
Observer - Padrões de projetoObserver - Padrões de projeto
Observer - Padrões de projetoEduardo Mendes
 
Introdução a Padrões de Projeto
Introdução a Padrões de ProjetoIntrodução a Padrões de Projeto
Introdução a Padrões de ProjetoEduardo Mendes
 
Top Issues Faced by Field Service Businesses & The Solution
Top Issues Faced by Field Service Businesses & The SolutionTop Issues Faced by Field Service Businesses & The Solution
Top Issues Faced by Field Service Businesses & The SolutionFingent Corporation
 
Apresentação Metodologia Intangible Assets Management DOM Strategy Partner...
 Apresentação  Metodologia Intangible Assets Management  DOM Strategy Partner... Apresentação  Metodologia Intangible Assets Management  DOM Strategy Partner...
Apresentação Metodologia Intangible Assets Management DOM Strategy Partner...DOM Strategy Partners
 
Abstração do banco de dados com PHP Doctrine
Abstração do banco de dados com PHP DoctrineAbstração do banco de dados com PHP Doctrine
Abstração do banco de dados com PHP DoctrineOtávio Calaça Xavier
 
TCC - Engenharia de Software Baseada em Componentes
TCC - Engenharia de Software Baseada em ComponentesTCC - Engenharia de Software Baseada em Componentes
TCC - Engenharia de Software Baseada em ComponentesJuliano Tiago Rinaldi
 
Fundamentos de Java
Fundamentos de Java Fundamentos de Java
Fundamentos de Java jmosorio777
 
Conhecendo Java
Conhecendo JavaConhecendo Java
Conhecendo JavaTI Infnet
 

Andere mochten auch (20)

Padrões de Projeto - Observer e Strategy
Padrões de Projeto - Observer e StrategyPadrões de Projeto - Observer e Strategy
Padrões de Projeto - Observer e Strategy
 
Padroes De Projeto
Padroes De ProjetoPadroes De Projeto
Padroes De Projeto
 
Exemplos de Design Patterns em Java
Exemplos de Design Patterns em JavaExemplos de Design Patterns em Java
Exemplos de Design Patterns em Java
 
Padrões de Projeto J2EE para Aplicações Web
Padrões de Projeto J2EE para Aplicações WebPadrões de Projeto J2EE para Aplicações Web
Padrões de Projeto J2EE para Aplicações Web
 
Introdução a Padrões de Projeto - Engenharia de Software
Introdução a Padrões de Projeto - Engenharia de SoftwareIntrodução a Padrões de Projeto - Engenharia de Software
Introdução a Padrões de Projeto - Engenharia de Software
 
Design patterns de uma vez por todas
Design patterns de uma vez por todasDesign patterns de uma vez por todas
Design patterns de uma vez por todas
 
Observer - Padrões de projeto
Observer - Padrões de projetoObserver - Padrões de projeto
Observer - Padrões de projeto
 
Introdução a Padrões de Projeto
Introdução a Padrões de ProjetoIntrodução a Padrões de Projeto
Introdução a Padrões de Projeto
 
design patterns java
design patterns javadesign patterns java
design patterns java
 
Aplicação da Engenharia de Domínio em um software para PPP
Aplicação da Engenharia de Domínio em um software para PPPAplicação da Engenharia de Domínio em um software para PPP
Aplicação da Engenharia de Domínio em um software para PPP
 
Top Issues Faced by Field Service Businesses & The Solution
Top Issues Faced by Field Service Businesses & The SolutionTop Issues Faced by Field Service Businesses & The Solution
Top Issues Faced by Field Service Businesses & The Solution
 
Apresentação Metodologia Intangible Assets Management DOM Strategy Partner...
 Apresentação  Metodologia Intangible Assets Management  DOM Strategy Partner... Apresentação  Metodologia Intangible Assets Management  DOM Strategy Partner...
Apresentação Metodologia Intangible Assets Management DOM Strategy Partner...
 
If bom é if morto
If bom é if mortoIf bom é if morto
If bom é if morto
 
GWT revista espirito
GWT revista espiritoGWT revista espirito
GWT revista espirito
 
Adote OpenJDK
Adote OpenJDKAdote OpenJDK
Adote OpenJDK
 
Desenvolvimento baseado em componentes
Desenvolvimento baseado em componentesDesenvolvimento baseado em componentes
Desenvolvimento baseado em componentes
 
Abstração do banco de dados com PHP Doctrine
Abstração do banco de dados com PHP DoctrineAbstração do banco de dados com PHP Doctrine
Abstração do banco de dados com PHP Doctrine
 
TCC - Engenharia de Software Baseada em Componentes
TCC - Engenharia de Software Baseada em ComponentesTCC - Engenharia de Software Baseada em Componentes
TCC - Engenharia de Software Baseada em Componentes
 
Fundamentos de Java
Fundamentos de Java Fundamentos de Java
Fundamentos de Java
 
Conhecendo Java
Conhecendo JavaConhecendo Java
Conhecendo Java
 

Ähnlich wie Padrões de Projeto - Design Patterns

TCC - Engenharia de Software Baseada em Componentes
TCC - Engenharia de Software Baseada em ComponentesTCC - Engenharia de Software Baseada em Componentes
TCC - Engenharia de Software Baseada em ComponentesJuliano Tiago Rinaldi
 
Tcc fábio oliveira_produção enxuta e layout aplicações de ferramentas computa...
Tcc fábio oliveira_produção enxuta e layout aplicações de ferramentas computa...Tcc fábio oliveira_produção enxuta e layout aplicações de ferramentas computa...
Tcc fábio oliveira_produção enxuta e layout aplicações de ferramentas computa...Louise Lage
 
Jspservlets
JspservletsJspservlets
JspservletsTiago
 
DissertacaoMScValterFinal20070216
DissertacaoMScValterFinal20070216DissertacaoMScValterFinal20070216
DissertacaoMScValterFinal20070216Valter Inacio Jr.
 
T(C)laudio(C)osenza - Consonância dos Objetivos da Governança Corporativa e d...
T(C)laudio(C)osenza - Consonância dos Objetivos da Governança Corporativa e d...T(C)laudio(C)osenza - Consonância dos Objetivos da Governança Corporativa e d...
T(C)laudio(C)osenza - Consonância dos Objetivos da Governança Corporativa e d...Claudio Cosenza, Manager, MBA
 
Apostila completa de access
Apostila completa de accessApostila completa de access
Apostila completa de accessmazinho1955
 
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejb
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejbK19 k23-integracao-de-sistemas-com-webservices-jms-e-ejb
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejbVinicius Fonseca
 
Programacao gtk
Programacao gtkProgramacao gtk
Programacao gtkTiago
 
Quanta
QuantaQuanta
QuantaTiago
 
Planejamento_e_Controle_de_Obras_Residen.pdf
Planejamento_e_Controle_de_Obras_Residen.pdfPlanejamento_e_Controle_de_Obras_Residen.pdf
Planejamento_e_Controle_de_Obras_Residen.pdfJenilsonPires1
 
Tcl tk
Tcl tkTcl tk
Tcl tkTiago
 
Cartilha-do-Docente-APNP-UFSC.pdf
Cartilha-do-Docente-APNP-UFSC.pdfCartilha-do-Docente-APNP-UFSC.pdf
Cartilha-do-Docente-APNP-UFSC.pdfWagner Carvalho
 
Desenvolvimento de sites responsivos utilizando o framework Bootstrap com apl...
Desenvolvimento de sites responsivos utilizando o framework Bootstrap com apl...Desenvolvimento de sites responsivos utilizando o framework Bootstrap com apl...
Desenvolvimento de sites responsivos utilizando o framework Bootstrap com apl...joselialcosta
 
Programacao cpp
Programacao cppProgramacao cpp
Programacao cppTiago
 

Ähnlich wie Padrões de Projeto - Design Patterns (20)

TCC - Engenharia de Software Baseada em Componentes
TCC - Engenharia de Software Baseada em ComponentesTCC - Engenharia de Software Baseada em Componentes
TCC - Engenharia de Software Baseada em Componentes
 
Tcc fábio oliveira_produção enxuta e layout aplicações de ferramentas computa...
Tcc fábio oliveira_produção enxuta e layout aplicações de ferramentas computa...Tcc fábio oliveira_produção enxuta e layout aplicações de ferramentas computa...
Tcc fábio oliveira_produção enxuta e layout aplicações de ferramentas computa...
 
Caelum html-css-javascript-php
Caelum html-css-javascript-phpCaelum html-css-javascript-php
Caelum html-css-javascript-php
 
K19 sql
K19 sqlK19 sql
K19 sql
 
Jspservlets
JspservletsJspservlets
Jspservlets
 
DissertacaoMScValterFinal20070216
DissertacaoMScValterFinal20070216DissertacaoMScValterFinal20070216
DissertacaoMScValterFinal20070216
 
T(C)laudio(C)osenza - Consonância dos Objetivos da Governança Corporativa e d...
T(C)laudio(C)osenza - Consonância dos Objetivos da Governança Corporativa e d...T(C)laudio(C)osenza - Consonância dos Objetivos da Governança Corporativa e d...
T(C)laudio(C)osenza - Consonância dos Objetivos da Governança Corporativa e d...
 
Uml
UmlUml
Uml
 
Apostila completa de access
Apostila completa de accessApostila completa de access
Apostila completa de access
 
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejb
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejbK19 k23-integracao-de-sistemas-com-webservices-jms-e-ejb
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejb
 
Programacao gtk
Programacao gtkProgramacao gtk
Programacao gtk
 
Quanta
QuantaQuanta
Quanta
 
Sql
SqlSql
Sql
 
Planejamento_e_Controle_de_Obras_Residen.pdf
Planejamento_e_Controle_de_Obras_Residen.pdfPlanejamento_e_Controle_de_Obras_Residen.pdf
Planejamento_e_Controle_de_Obras_Residen.pdf
 
ink2canvas
ink2canvasink2canvas
ink2canvas
 
Tcl tk
Tcl tkTcl tk
Tcl tk
 
Cartilha-do-Docente-APNP-UFSC.pdf
Cartilha-do-Docente-APNP-UFSC.pdfCartilha-do-Docente-APNP-UFSC.pdf
Cartilha-do-Docente-APNP-UFSC.pdf
 
Html
HtmlHtml
Html
 
Desenvolvimento de sites responsivos utilizando o framework Bootstrap com apl...
Desenvolvimento de sites responsivos utilizando o framework Bootstrap com apl...Desenvolvimento de sites responsivos utilizando o framework Bootstrap com apl...
Desenvolvimento de sites responsivos utilizando o framework Bootstrap com apl...
 
Programacao cpp
Programacao cppProgramacao cpp
Programacao cpp
 

Padrões de Projeto - Design Patterns

  • 1. PÓS-GRADUAÇÃO EM ANÁLISE E GESTÃO DE SISTEMAS DE INFORMAÇÃO DÁVISSON HÚDSON CHAVES BERNADETE EDUARDO COELHO CARNEIRO FILIPE ARANTES FERNANDES PADRÕES DE PROJETO (DESIGN PATTERNS) Trabalho da Disciplina de Reutilização de Software Campos do Goytacazes, RJ 2013
  • 2. RESUMO Padrões de projeto são padrões que visam estruturar soluções para problemas antes encontrados em projetos de software, facilitando assim a criação de novos projetos já que apresentam soluções eficazes para problemas conhecidos. Padrões de projetos não são de fácil aplicação quando não se domina os conceitos que envolvem orientação a objetos, porém tornam-se de grande ajuda para desenvolvedores e projetistas mais experientes, facilitando bastante o trabalho. Padrões de projetos podem ser classificados de forma geral como de criação, estrutural e comportamental, cada tipo atua de forma diferente no tratamento dos objetos e classes. Padrões de projetos tendem a maximizar a qualidade do projeto, tornando-os mais flexíveis e possibilitando um melhor reuso de código. Os padrões de projeto mais conhecidos e utilizados são os 23 padrões do grupo conhecido como GoF (Gang of Four), e com base principal no trabalho deles, o presente trabalho aborda os padrões Abstract Factory, Decorator, Composite, Chain of Responsibility, Observer, Strategy, Template Method e Visitor com exemplos de código e explicações.
  • 3. LISTA DE FIGURAS Figura 1. Os 23 Padrões GoF (PEREIRA, 2013)............................................................................. 14 Figura 2. Estrutura do Padrão Abstract Factory (GAMMA et al., 2000)...................................... 18 Figura 3. Diagrama de classe fábrica de carros (BRIZENO, 2011) ............................................... 20 Figura 4. Estrutura padrão do Composite................................................................................... 23 Figura 5. Exemplo de implementação do padrão Composite..................................................... 24 Figura 6. Estrutura do padrão Decorator.................................................................................... 29 Figura 7. Exemplo de implementação do padrão Decorator...................................................... 30 Figura 8. Estrutura do Chain of Responsability........................................................................... 34 Figura 9. Diagrama de classes do exemplo do padrão Chain of Responsability ......................... 37 Figura 10. Estrutura do padrão Observer (GAMMA et al, 2000). ............................................... 39 Figura 11. Diagrama de sequência entre um subject e dois observadores (GAMMA et al, 2000). ..................................................................................................................................................... 40 Figura 12. Diagrama de classes da estação meteorológica......................................................... 41 Figura 13. Estrutura do Padrão Strategy (GAMMA et al., 2000)................................................. 46 Figura 14. Diagrama de classe do exemplo do padrão Visitor.................................................... 50 Figura 15. Diagrama de sequência do padrão Visitor ................................................................. 53 Figura 16. Diagrama de classes do exemplo de Visitor............................................................... 54
  • 4. LISTA DE BLOCOS Bloco 1. Interface FabricaDeCarro .............................................................................................. 20 Bloco 2. Classe FabricaFiat .......................................................................................................... 20 Bloco 3. Interfaces CarroPopular e CarroSedan.......................................................................... 21 Bloco 4. Implementação das interfaces CarroPopular e CarroSedan......................................... 21 Bloco 5. Classe de teste da Fábrica de Carros............................................................................. 22 Bloco 6. Implementação da classe MenuComponent................................................................ 25 Bloco 7. Implementação da classe MenuItem............................................................................ 26 Bloco 8. Implementação da classe Waitress............................................................................... 26 Bloco 9. Implementação da classe MenuItem............................................................................ 27 Bloco 10. Implementação da classe MenuTestDrive .................................................................. 28 Bloco 11. Implementação da classe Beverage............................................................................ 31 Bloco 12. Implementação das classes dos condimentos ............................................................ 32 Bloco 13. Implementação da classe StarbuzzCoffee................................................................... 33 Bloco 14. Implementação da enumeração de IDBancos ............................................................ 34 Bloco 15. Implementação da classe BancoChain........................................................................ 35 Bloco 16. Implementação do banco concreto ............................................................................ 36 Bloco 17. Implemantação do padrão Chain of Responsability ................................................... 36 Bloco 18. Interfaces Subject, Observer e DisplayElement .......................................................... 42 Bloco 19. Classe WeatherData.................................................................................................... 43 Bloco 20. Implemnetação das interfaces Observer e DisplayElement em CurrentConditionDisplay............................................................................................................. 44 Bloco 21. Criação do objeto weatherData e as 3 exibições ........................................................ 44 Bloco 22. Interface CalculaImposto ............................................................................................ 47 Bloco 23. Implementaação do imposto de 20% ou 15%............................................................. 48 Bloco 24. Método construtor de Funcionario............................................................................. 48 Bloco 25. Classe Usuario. ............................................................................................................ 50 Bloco 26. Classe AbstractLogin.................................................................................................... 51 Bloco 27. Classes LoginPorArquivo e LoginPorBD....................................................................... 52 Bloco 28. Interfaces Visitable e Visitor........................................................................................ 55 Bloco 29. Classe abstrata Place................................................................................................... 55 Bloco 30. Implementação de Visitable na classe City. ................................................................ 55 Bloco 31. Classes Museum e Park............................................................................................... 56 Bloco 32. Classe FirstTimeVisitor. ............................................................................................... 57 Bloco 33. Classe JobSeekerVisitor............................................................................................... 57
  • 5. Sumário 1. INTRODUÇÃO .................................................................................................................... 7 1.1. MOTIVAÇÃO E JUSTIFICATIVA............................................................................. 7 1.2. OBJETIVOS ................................................................................................................. 8 1.3. ORGANIZAÇÃO DO TRABALHO............................................................................ 8 2. REFERENCIAL TEÓRICO ................................................................................................. 9 2.1. REUTILIZAÇÃO.......................................................................................................... 9 2.2. ENCAPSULAMENTO................................................................................................. 9 2.3. HERANÇA, COMPOSIÇÃO, POLIMORFISMO E INTERFACE........................... 10 2.4. MANUTENIBILIDADE E GRANULARIDADE...................................................... 11 3. PADRÕES DE PROJETO (DESIGN PATTERNS)........................................................... 12 3.1. PADRÕES DE CRIAÇÃO ......................................................................................... 14 3.2. PADRÕES ESTRUTURAIS....................................................................................... 15 3.3. PADRÕES COMPORTAMENTAIS.......................................................................... 16 4. DESCREVENDO E EXEMPLIFICANDO ALGUNS PADRÕES.................................... 17 4.1. ABSTRACT FACTORY ............................................................................................ 17 4.1.1. Exemplo de Abstract Factory .............................................................................. 19 4.2. COMPOSITE .............................................................................................................. 22 4.2.1. Exemplo do Composite........................................................................................... 24 4.3. DECORATOR ............................................................................................................ 29 4.3.1. Exemplo do Decorator ........................................................................................ 30 4.4. CHAIN OF RESPONSIBILITY................................................................................. 33 4.4.1. Exemplo do Chain of Responsability ................................................................... 34 4.5. OBSERVER................................................................................................................ 37 4.5.1. Exemplo de Observer.......................................................................................... 41 4.6. STRATEGY................................................................................................................ 45 4.6.1. Exemplo de padrão Strategy............................................................................... 47 4.7. TEMPLATE METHOD.............................................................................................. 49 4.7.1. Exemplo do Template Method............................................................................ 49 4.8. VISITOR..................................................................................................................... 53 4.8.1. Exemplo de Visitor .............................................................................................. 54 5. PADRÕES NÃO GOF........................................................................................................ 58 5.1. SOA DESIGN PATTERNS........................................................................................ 58
  • 6. 6. CONCLUSÕES................................................................................................................... 59 6.1. CONTRIBUIÇÕES..................................................................................................... 59 6.2. LIMITAÇÕES............................................................................................................. 60 REFERÊNCIAS BIBLIOGRÁFICAS........................................................................................ 61
  • 7. 7 1. INTRODUÇÃO Padrões de projeto podem ser vistos como uma solução que já foi testada para um problema, ou seja, geralmente descreve uma solução ou uma instância da solução que foi utilizada para resolver um problema específico. Padrões de projetos são soluções para problemas que alguém um dia teve e resolveu aplicando um modelo que foi documentado e adaptado integralmente ou de acordo com a necessidade de uma solução (MACORATTI, 2002). Um padrão de projeto deve auxiliar e prever alterações de um projeto. Segundo Freeman et al. (2004), alteração é a única coisa com a qual podemos contar sempre no desenvolvimento de software, independentemente de como seja desenvolvido um aplicativo, com o tempo ele precisa crescer e mudar para não morrer. Os padrões de projeto nos dizem como resolver alguns problemas, porém não dizem como adaptar esses projetos para adequá-los aos aplicativos, pois eles estão num nível acima das bibliotecas (FREEMAN et al., 2004). Além disso, fornecem uma linguagem compartilhada que pode maximizar o valor da comunicação entre desenvolvedores. 1.1. MOTIVAÇÃO E JUSTIFICATIVA Frequentemente desenvolvedores deparam-se com problemas que já foram resolvidos em projetos anteriores, com isso surgiu a necessidade de se criar padrões como uma ajuda na resolução de problemas baseados em soluções que já funcionavam em projetos já desenvolvidos. Assim, o agrupamento dessas soluções tende a ajudar na construção de projetos melhores e com maior manutenibilidade e granularidade.
  • 8. 8 1.2. OBJETIVOS Este trabalho visa explorar os conceitos de Padrões de Projeto, bem como apresentar exemplos de alguns padrões escolhidos. Este trabalho se baseia nos padrões de Gamma et al. (2000), porém também são apresentados alguns padrões de projeto diferentes da abordagem principal, não se restringindo necessariamente a uma única linha de pesquisa. 1.3. ORGANIZAÇÃO DO TRABALHO De forma geral o trabalho apresenta mais cinco capítulos além desta introdução, conforme descrito a seguir. No capítulo 2, é apresentado um referencial teórico, onde observa-se os conceitos de reutilização de software, encapsulamento, herança, composição, polimorfismo, interface, manutenibilidade e granularidade. Esses conceitos estão presentes de forma intrínseca em um projeto de Padrão de Projetos e por isso ganharam espaço no referencial teórico. O capítulo 3 aborda de forma mais profunda questões sobre design patterns, o que são e para que servem, as principais propriedades dos padrões de projeto, apresentará os prós e os contras de se implantar um padrão de projeto em determinados projetos, os componentes principais de um padrão de projeto, requisitos de um bom sistema de padrões, e como se utilizar padrões de projeto. No capítulo 4 alguns padrões foram escolhidos para exemplificar o estudo de Design Patterns realizado, os exemplos foram feitos em Java na maior parte. Alguns padrões não desenvolvidos ou agrupados por Gamma et al são apresentados no capítulo 5, porém sem muita ênfase, apenas a título de informação. No capítulo 6, e último, são apresentadas algumas conclusões obtidas durante o desenvolvimento do trabalho.
  • 9. 9 2. REFERENCIAL TEÓRICO 2.1. REUTILIZAÇÃO A Reutilização é uma atividade já realizada há muito tempo por desenvolvedores e projetistas de software. Embora a mesma seja feita de uma maneira ad hoc, ideias, objetos, argumentos e abstrações sempre foram reutilizados por desenvolvedores de software (PRESSMAN, 2006). A reutilização pode ser definida como o processo de criação de sistemas a partir de software preexistente (KRUEGER, 1992), trazendo consigo a promessa de aumentar a produtividade e diminuir custos de desenvolvimento, além de melhorar a qualidade do produto, através de artefatos de software já testados e utilizados em outros contextos (FRAKES e KANG, 2005). A reutilização de software não é uma técnica nova, ela surgiu no final dos anos 60, porém, anteriormente, se reutilizava apenas bibliotecas de rotinas ou partes de código em ambientes de programação, mas com a orientação a objeto (OO) passou-se a utilizar as classes para encapsular dados e funções, aumentando a granularidade (ODYSSEY, 2007). A reutilização representa uma subárea da Engenharia de Software, esta busca melhorar a qualidade dos artefatos de software e diminuir o tempo e esforços necessários para produzi-los, assim como a intenção da reutilização. Em uma organização o desenvolvimento pode ser para ou com reutilização, dependendo do interesse. O desenvolvimento de software para reutilização tem como fim produzir os artefatos para que sejam reutilizados futuramente, e no desenvolvimento de software com reutilização, artefatos são incorporados ao sistema (BERNADETE et al., 2007). 2.2. ENCAPSULAMENTO Encapsular, de forma geral, significa esconder os dados, ou seja, não deixar campos expostos para serem manipulados diretamente a partir de código externo, o que lavaria a violações da invariante de representação ou a dependências indesejáveis que
  • 10. 10 impedem a alteração da implementação (MACORATTI, 2002). Segundo Macoratti (2002) devemos esconder alguns componentes, permitindo apenas acessos estilizados ao objeto, porém o acesso indireto pode reduzir o desempenho. O encapsulamento serve para controlar o acesso aos atributos e métodos de uma classe, e também é uma forma eficiente de proteger os dados manipulados dentro da classe, além de determinar onde esta classe poderá ser manipulada (LEMOS, 2013). Então para ter um método encapsulado utilizamos um modificador de acesso que geralmente é público, além do tipo de retorno dele (LEMOS, 2013). Encapsular é fundamental para que o sistema seja suscetível a mudanças, assim não é preciso mudar uma regra de negócio em vários lugares, mas sim em apenas um único lugar, já que a regra está encapsulada (CAELUM, 2011). 2.3. HERANÇA, COMPOSIÇÃO, POLIMORFISMO E INTERFACE As duas maneiras mais comuns para reutilização de funcionalidades em sistemas orientados a objetos são herança de classe e composição de objetos, a herança de classe permite definir a implementação de uma classe em termos da implementação de outra, já a composição por objetos é uma alternativa á herança onde a nova funcionalidade é obtida pela montagem ou composição de objetos para obter funcionalidades mais complexas (GAMMA et al., 2000). A herança é um mecanismo da Orientação a Objeto que permite criar novas classes a partir de classes já existentes, aproveitando-se das características existentes na classe a ser estendida (LEMOS, 2013). Com herança é possível criar classes derivadas, subclasses e superclasses. Herança pode ser associada com o termo “é um”. Composição estende uma classe e delega o trabalho para o objeto desta classe, onde uma instância da classe existente é usada como componente da outra classe (MACORATTI, 2011). Composição pode ser associada com o termo “tem um”. Usando composição os objetos que foram instanciados e estão contidos na classe que os instanciou são acessados somente através de sua interface, além disso, uma composição deve ser definida dinamicamente em tempo de execução pela obtenção de referência de objetos a objetos do mesmo tipo e apresenta uma menor dependência de implementações (MACORATTI, 2011).
  • 11. 11 Uma interface nada mais é do que um bloco de código definindo um tipo e os métodos e atributos que esse tipo deve possuir. Na prática o que acontece é que qualquer classe que quiser ser do tipo definido pela interface deve implementar os métodos dessa interface (LEMOS, 2013). Segundo a Caelum (2011), uma interface pode ser vista como um “contrato”, onde quem assinar esse contrato é obrigado, nesse caso, a implementar os métodos da interface, não se herda métodos e atributos, mas sim responsabilidades. Uma interface pode herdar de mais de uma interface, o que pode nos levar a um melhor uso do polimorfismo. Polimorfismo é o princípio pelo qual duas ou mais classes derivadas de uma mesma superclasse podem invocar métodos que têm a mesma identificação, assinatura, mas comportamentos distintos, especializados para cada classe derivada (LEMOS, 2013). Polimorfismo é a capacidade de um objeto poder ser referenciado de várias formas, porém isso não significa que o objeto fica se transformando, pelo contrário, um objeto nasce de um tipo e morre do mesmo tipo, o que pode mudar é a maneira como nos referimos a ele (CAELUM, 2011). É sempre bom programar pensando na interface da classe, como seus usuários a estarão utilizando, e não somente em como ela irá funcionar (GAMMA et al, 2000). 2.4. MANUTENIBILIDADE E GRANULARIDADE Manutenibilidade é uma das características de qualidade de software, determinando o grau de facilidade com que o mesmo pode ser corrigido ou aperfeiçoado, assim um software com alto índice de manutenibilidade necessita de menos tempo e pessoas para ser modificado (BRUSAMOLIN, 2004). Manutenibilidade de software diz respeito à facilidade com que o mesmo pode ser modificado para satisfazer requisitos do usuário ou ser corrigido quando deficiências são detectadas (PIGOSKI, 1996). Granularidade diz respeito ao nível de detalhamento da classe ou objeto, assim quanto mais granular for um software, mais partes menores ele vai ter. Um sistema granular tem um número maior de objetos com tarefas mais específicas, ao passo que um sistema menos granular possui poucas classes, porém classes maiores, com mais funcionalidades por exemplo.
  • 12. 12 Granularidade demais impacta no processamento e dificulta o desenvolvimento, porém granularidade a menos deixa o código com pouca manutenibilidade e menos coeso. 3. PADRÕES DE PROJETO (DESIGN PATTERNS) Segundo Macoratti (2002), padrões para arquitetura de software são soluções de eficiência já comprovadas e amplamente utilizadas para a resolução de problemas comuns em projeto de software, que são desenvolvidas e conhecidas por especialistas e tornam-se padrões por serem reutilizadas várias vezes em vários projetos, tendo eficácia comprovada. Padrões de projeto são descrições de objetos e classes comunicantes que precisam ser personalizadas para resolver um problema geral de projeto num contexto particular (GAMMA et al., 2000). É importante observar que um padrão de projeto deve nomear, abstrair e identificar os aspectos que dão base a uma estrutura de projeto comum para torná-la reutilizável, focalizando um problema ou particularidade do projeto orientado a objetos. A utilização de padrões possibilita uma maior coesão e minimização da complexidade e do acoplamento entre os elementos que integram a aplicação (PEREIRA, 2008). Com um padrão de projeto é mais fácil reutilizar projetos e arquiteturas bem- sucedidas, porém, somente devem ser considerados projetos que foram aplicados mais de uma vez em diferentes sistemas, pois é necessário comprovar a eficiência e a eficácia da solução para ser considerado um padrão de projeto, assim nenhum padrão de projeto descreve projetos novos ou não testados. Conhecer conceitos como abstração, herança e polimorfismo são importantes, mas não suficientes para ser um bom projetista, é necessário criar projetos flexíveis que sejam fáceis de manter e modificar (FREEMAN et al., 2004). Segundo Gamma et al. (2000), um padrão tem quatro elementos essenciais: nome, problema, solução e consequências. Eles descrevem esses elementos da seguinte forma: o nome do padrão é uma referência que deve descrever um problema de projeto, suas soluções e consequências em uma ou duas palavras; o problema descreve em que
  • 13. 13 situação aplicar o padrão, deve explicar o problema e seu contexto; a solução descreve os elementos que compõem o padrão de projeto, seus relacionamentos, suas responsabilidades e colaborações, o padrão fornece uma descrição abstrata de um problema de projeto e como um arranjo geral de elementos o resolve; as consequências são os resultados e análises das vantagens e desvantagens da aplicação do padrão. Dentre as principais propriedades dos padrões de projetos podemos citar que capturam o conhecimento e a experiência de especialistas em projetos de software, auxiliam o projeto de arquiteturas mais complexas (MACORATTI, 2002), especificam abstrações que estão acima do nível de classes ou objetos isolados ou de componentes e definem um vocabulário comum para discussão de problemas e soluções de projeto (GAMMA et al., 2000), facilitam a documentação e manutenção da arquitetura do software e também auxiliam o projeto de uma arquitetura com determinadas propriedades (BUSCHMANN et al., 1996). Como benefícios da utilização de padrões podemos destacar, segundo Macoratti (2002): • Fornecem soluções que já foram testadas e aprovadas. • Tornam o sistema mais fácil de entender e manter. • Facilitam o desenvolvimento de módulos coesos. • A comunicação entre os participantes do projeto fica mais eficiente. Como desvantagens pode-se citar o aumento da complexidade de entendimento se não houver grande conhecimento de conceitos OO por parte dos envolvidos, e também por adicionar acessos indiretos ou ao aumentar a quantidade de código, contudo podem aumentar a capacidade de compreensão ao melhorar a modularidade, separando melhor os conceitos e simplificando a descrição (UNIVERSIA). Os requisitos para um bom sistema de padrões segundo Macoratti (2002): o sistema deve conter uma boa quantidade de padrões; a descrição do padrão de seguir um formato padronizado; o sistema deve ser estruturado; o sistema deve mostrar o relacionamento entre os padrões e sua estrutura deve permitir evolução. Para se utilizar padrões devemos ter bom senso, não adianta sair implementando padrões sem ter certeza do porque utilizá-los, então o melhor é implementar a solução e verificar se ela funciona para assim poder refatorá-la com os padrões identificados para a melhoria e correção das deficiências do projeto.
  • 14. 14 Os padrões criados por Gamma et al. (2000) são os mais conhecidos atualmente, e de acordo com eles os padrões podem ser de 3 tipos: padrões de criação, estruturais e comportamentais. A figura 1 mostra a divisão dos padrões. Figura 1. Os 23 Padrões GoF (PEREIRA, 2013) 3.1. PADRÕES DE CRIAÇÃO Os padrões de criação abstraem o processo de instanciação, ajudam a tornar um sistema independente de como seus objetos são criados, compostos e representados (GAMMA et al., 2000). Todos os padrões de criação encapsulam conhecimento sobre quais classes concretas são usadas pelo sistema, e todas ocultam o modo como as instâncias destas classes são criadas e compostas, a única coisa que o sistema sabe é que suas classes são definidas por classes abstratas (GAMMA et al., 2000). Porém um padrão de criação dá muita flexibilidade ao que, como e quando é criado e a quem cria (GAMMA et al., 2000). Uma descrição geral dos padrões de criação é apresentada a seguir. Abstract Factory – Fornece uma interface para criação de famílias de objetos relacionadas ou dependentes sem especificar suas classes concretas. Builder – Separa a construção de um objeto complexo da sua representação, de forma que o mesmo processo de construção possa criar diferentes representações.
  • 15. 15 Factory Method – Define uma interface para instanciação de objetos, mas deixa as subclasses decidirem qual classe deve ser instanciada. Prototype – Especifica os tipos de objetos a serem criados usando uma instância prototípica e cria novos objetos copiando esse protótipo. Singleton – Garante que para uma classe específica só possa existir uma única instância, fornecendo um ponto global de acesso para ela. 3.2. PADRÕES ESTRUTURAIS Os padrões estruturais se preocupam com a forma como classes e objetos são compostos para formar estruturas maiores, eles utilizam herança para compor interfaces ou implementações (GAMMA et al., 2000). Este tipo de padrão é bastante útil para fazer bibliotecas de classes independentes trabalharem juntas. Nesse padrão os padrões estruturais de objetos descrevem maneiras de compor objetos para obter novas funcionalidades, assim a flexibilidade obtida pela composição de objetos provém da capacidade de mudar a composição em tempo de execução (GAMMA et al., 2000). Uma descrição geral dos padrões estruturais é apresentada a seguir. Adapter – Converte a interface de uma classe em outra interface esperada pelos clientes. Permite que dois objetos se comuniquem mesmo que tenham interfaces incompatíveis. Bridge – Separa uma abstração de sua implementação, de forma que as duas possam variar independentemente. Oculta detalhes de implementação dos clientes. Composite – Permite que os clientes tratem objetos individuais e composições de objetos de maneira uniforme. Ele lida com uma estrutura de elementos agrupada hierarquicamente. Decorator – Atribui responsabilidades adicionais a um objeto dinamicamente. Ele fornece uma alternativa flexível a subclasses para a extensão da funcionalidade. Facade – Fornece uma interface unificada para u conjunto de interfaces em um subsistema, tornando o subsistema mais fácil de usar. Flyweight – Usa compartilhamento para dar suporte a vários objetos de forma eficiente.
  • 16. 16 Proxy – Fornece um objeto representante ou procurador de outro objeto para controlar o acesso ao mesmo. 3.3. PADRÕES COMPORTAMENTAIS Este tipo de padrão se preocupa com algoritmos e a atribuição de responsabilidade entre objetos, eles não descrevem somente padrões de objetos ou classes, mas também os padrões de comunicação entre eles, contudo, caracterizam fluxos de controle difíceis de seguir em tempo de execução (GAMMA et al., 2000). Padrões comportamentais de classe utilizam herança para distribuir o comportamento entre as classes enquanto os padrões comportamentais de objetos utilizam composição de objetos (GAMMA et al., 2000). Uma descrição geral dos padrões comportamentais é apresentada a seguir. Chain of Responsibility – Evita dependência do remetente (cliente) de uma requisição ao seu destinatário, dando a oportunidade de mais de um objeto tratar a requisição. Ele encadeia os objetos receptores e passa a solicitação ao longo da cadeia até que um objeto a trate. Command – Encapsula uma solicitação como um objeto, permitindo parametrizar clientes com diferentes solicitações, enfileirar ou registrar solicitações e suportar operações que podem ser desfeitas. Interpreter – Dada uma linguagem, define-se uma representação para sua gramática juntamente com um interpretador que usa a representação para interpretar sentenças nessa linguagem. Iterator – Provê uma forma de percorrermos os elementos de uma coleção sem violar o seu encapsulamento. Mediator – Cria um objeto que age como um mediador controlando a interação entre um conjunto de objetos, ou seja, encapsula a forma como um conjunto de objetos interage. Memento – Torna possível salvar o estado de um objeto de modo que o mesmo possa ser restaurado, sem violar o encapsulamento. Observer – Define uma relação de dependência 1:N de forma que quando um certo objeto (assunto) tem seu estado modificado os demais (observadores) são
  • 17. 17 notificados e atualizados. Possibilita baixo acoplamento entre os objetos observadores e o assunto. State – Permite a um objeto alterar seu comportamento quando estado interno muda. Strategy – Define uma família de algoritmos, encapsula cada um deles e os torna intercambiáveis. Permite que o algoritmo varie independentemente dos clientes que o utilizam. Template Method – Define o esqueleto de um algoritmo em uma operação adiando a definição de alguns passos para as subclasses. Ele permite que as subclasses redefinam certos passos de um algoritmo sem mudar a sua estrutura. Visitor – Define operações independentes a serem realizadas sobre elementos de uma estrutura. 4. DESCREVENDO E EXEMPLIFICANDO ALGUNS PADRÕES Este capítulo apresenta alguns padrões escolhidos para exemplificar o estudo de Design Patterns realizado. Os exemplos são exibidos em Java e/ou Python. 4.1. ABSTRACT FACTORY Criar objetos é mais do que simplesmente usar o operador new, criar instâncias nem sempre deve ser feito de forma pública, isso pode gerar problemas de ligação (FREEMAN et al., 2004). Os padrões Factory podem ajudar nessa situação. As factories (fábricas) cuidam dos detalhes da criação dos objetos. Segundo Gamma et al. (2000), o padrão Abstract Factory, também conhecido como kit, fornece uma interface para criação de famílias de objetos relacionados ou dependentes sem especificar suas classes concretas. Abstract Factory permite que um cliente use uma interface abstrata para criar um conjunto de produtos relacionados se saber, ou importar-se, sobre os produtos
  • 18. concretos que são realmente produzidos, assim o cliente é desvinculado de qualquer especificação dos produtos concretos (FREEMAN Segundo Gamma et al • Um sistema deve ser independente de como seus produtos compostos ou representados; • Um sistema deve ser configurado como um produto de uma família de múltiplos produtos; • Uma família de objetos conjunto, e for necessário garantir essa restrição; • Intende-se fo revelar-se somente suas interfaces, não suas implementações. Baseado em Gamma Figura 2. Estrutura do Padrão Abstract Assim temos os participantes de acordo compilação de Gamma et al • AbstractFactory objetos-produto abstratos concretas devem implementar, o que consiste em um conjunto de métodos para fabricar produtos; • Concrete Factory concretos. que são realmente produzidos, assim o cliente é desvinculado de qualquer especificação dos produtos concretos (FREEMAN et al., 2004). et al. (2000), este padrão deve ser aplicado quando: Um sistema deve ser independente de como seus produtos compostos ou representados; Um sistema deve ser configurado como um produto de uma família de múltiplos produtos; Uma família de objetos-produto for projetada para ser usada em conjunto, e for necessário garantir essa restrição; se fornecer uma biblioteca de classes de produtos e quer se somente suas interfaces, não suas implementações. Baseado em Gamma et al. (2000) a estrutura do padrão é apresentada a seguir: . Estrutura do Padrão Abstract Factory (GAMMA et al., 2000) Assim temos os participantes de acordo da figura 2 explicitados segundo uma et al. (2000) e Freeman et al. (2004): Factory – Declara uma interface para operações que criam produto abstratos. Define a interface que todas as fábricas concretas devem implementar, o que consiste em um conjunto de métodos para fabricar produtos; Concrete Factory – Implementa as operações que criam objetos As fábricas concretas implementam as diferentes famílias de 18 que são realmente produzidos, assim o cliente é desvinculado de qualquer . (2000), este padrão deve ser aplicado quando: Um sistema deve ser independente de como seus produtos são criados, Um sistema deve ser configurado como um produto de uma família de produto for projetada para ser usada em rnecer uma biblioteca de classes de produtos e quer se somente suas interfaces, não suas implementações. . (2000) a estrutura do padrão é apresentada a seguir: explicitados segundo uma Declara uma interface para operações que criam . Define a interface que todas as fábricas concretas devem implementar, o que consiste em um conjunto de mplementa as operações que criam objetos-produto ferentes famílias de
  • 19. 19 produtos, e para criar um produto o cliente usa uma dessas fábricas, assim nunca precisa criar a instância do objeto de um produto; • AbstractProduct – Declara uma interface para um tipo de objeto- produto. É a família de produtos onde cada fábrica concreta pode produzir um conjunto inteiro de produtos; • ConcreteProduct – Define um objeto-produto a ser criado pela correspondente fábrica concreta. Também implementa a interface de Abstract Product. • Client – Usa somente interfaces declaradas pelas classes Abstract Factory e Abstract Product. Em suma, é escrita para a Abstract Factory e, depois, composta no tempo de execução com a Abstract Product. Uma única instância de uma classe ConcreteFactory é criada em tempo de execução normalmente. Para criar diferentes objetos-produto, os clientes deveriam usar fábricas concretas diferentes (GAMMA et al., 2000). Segundo Freeman et al. (2000), geralmente os métodos de uma Abstract Factory são implementados como Factory Methods. O trabalho de uma Abstract Factory é definir uma interface para criar um conjunto de produtos, e cada método nessa interface é responsável pela criação de um produto concreto, assim implementamos uma subclasse da Abstract Factory para fornecer essas implementações, dessa forma percebe-se que os Factory Methods são uma forma natural de implementar métodos concretos nas Abstract Factory. As classes Abstract Factory são frequentemente implementadas com Factory Methods, mas elas também podem ser implementadas usando Prototype, além disso, uma fábrica concreta é frequentemente um Singleton (GAMMA et al., 2000). As consequências de se usar esse padrão são apontadas por Gamma et al. (2000): Isolamento das classes concretas; fácil troca de famílias de produtos; promove harmonia entre produtos; difícil de suportar novos tipos de produtos. 4.1.1. Exemplo de Abstract Factory Para Abstract Factory utilizou-se o exemplo de Brizeno (2011), que consiste na representação de um sistema que, dado um conjunto de carros devemos manipulá-los.
  • 20. Deve ser feito um agrupamento dos carros em conjuntos, de forma a agrupar objetos que tenham comportamentos parecidos. Para exemplificar os objetos foram organizados da seguinte forma: Sedan (Siena – Fiat Popular (Palio – Fiat Assim o que deve ser feito é agrupar conjunto de carros Popular para cada uma das fábricas. do projeto de fábricas de carros Sedan e Popular. Figura 3. Diagrama de c O bloco 1 mostra uma interface para criação de Factories. Cada fábrica cria um objeto de cada tipo, nesse caso um método para carros Sedan e outro para carros Populares. public class FabricaFiat @Override public CarroSedan criarCarroSedan() { return new Siena(); } @Override public CarroPopular criarCarroPopular( return new Palio(); } public interface FabricaDeCarro { CarroSedan criarCarroSedan(); CarroPopular criarCarroPopular(); } agrupamento dos carros em conjuntos, de forma a agrupar objetos que tenham comportamentos parecidos. Para exemplificar os objetos foram organizados da seguinte forma: Fiat, Fiesta Sedan – Ford); Fiat, Fiesta – Ford). o que deve ser feito é agrupar um conjunto de carros S conjunto de carros Popular para cada uma das fábricas. A figura 3 apresenta a estrutura do projeto de fábricas de carros Sedan e Popular. . Diagrama de classe fábrica de carros (BRIZENO, 2011) mostra uma interface para criação de Factories. Cada fábrica cria um objeto de cada tipo, nesse caso um método para carros Sedan e outro para carros FabricaFiat implements FabricaDeCarro { CarroSedan criarCarroSedan() { Siena(); CarroPopular criarCarroPopular() { Palio(); FabricaDeCarro { CarroSedan criarCarroSedan(); CarroPopular criarCarroPopular(); Bloco 1. Interface FabricaDeCarro Bloco 2. Classe FabricaFiat 20 agrupamento dos carros em conjuntos, de forma a agrupar objetos Para exemplificar os objetos foram organizados da seguinte forma: um conjunto de carros Sedan e outro apresenta a estrutura mostra uma interface para criação de Factories. Cada fábrica cria um objeto de cada tipo, nesse caso um método para carros Sedan e outro para carros
  • 21. 21 O bloco 2 cria os carros de fato, instanciando-os. Todas as outras fábricas necessitam implementar a interface FabricaDeCarro. A seguir a criação de mais duas interfaces: Os dois métodos apresentados nas interfaces do bloco 3 exibem as informações de seus tipos de carro, e apesar dos métodos executarem a mesma operação poderíamos supor que os carros populares estão em um banco de dados e os sedans em outro, assim cada método precisa criar sua própria conexão. O bloco 4 apresenta os produtos concretos implementando suas interfaces. public class Palio implements CarroPopular { @Override public void exibirInfoPopular() { System.out.println("Modelo: PalionFábrica: FiatnCategoria:Popular"); } } public class Siena implements CarroSedan { @Override public void exibirInfoSedan() { System.out.println("Modelo: SienanFábrica: FiatnCategoria:Sedan"); } } public interface CarroPopular { void exibirInfoPopular(); } public interface CarroSedan { void exibirInfoSedan(); } Bloco 3. Interfaces CarroPopular e CarroSedan Bloco 4. Implementação das interfaces CarroPopular e CarroSedan
  • 22. 22 Analisando o bloco 5 percebe-se que foi criada uma fábrica abstrata e foi colocado nela qualquer fábrica, de acordo com a necessidade, e de forma semelhante foi criada referências para um carro Popular e para um carro Sedan, e ainda de acordo com nossas necessidades foram sendo utilizados os carros dos fabricantes. Segundo Brizeno (2011) com esse padrão criamos uma estrutura muito grande de classes e interfaces para resolver o problema de criação de objetos, porém baseado no princípio da Segregação de Interface isto é uma coisa boa, pois o código cliente fica dependendo de interfaces simples e pequenas ao invés de depender de uma interface grande e que nem todos os métodos seriam utilizados. 4.2. COMPOSITE O Composite é um tipo de padrão estrutural e tem como objetivo permitir a composição de objetos em estruturas de árvore para representar hierarquias parte-todo possibilitando o tratamento de objetos individuais ou composições de objetos de modo uniforme. Segundo Gamma et al. (2000), Composite deve tratar objetos primitivos e objetos recipientes de modo diferente, mesmo se na maior parte do tempo o usuário os trata de forma idêntica. Ter que distinguir entre esses objetos torna a aplicação mais complexa. O padrão Composite descreve como usar a composição recursiva de maneira que os clientes não tenham que fazer essa distinção. public static void main(String[] args) { FabricaDeCarro fabrica = new FabricaFiat(); CarroSedan sedan = fabrica.criarCarroSedan(); CarroPopular popular = fabrica.criarCarroPopular(); sedan.exibirInfoSedan(); System.out.println(); popular.exibirInfoPopular(); System.out.println(); fabrica = new FabricaFord(); sedan = fabrica.criarCarroSedan(); popular = fabrica.criarCarroPopular(); sedan.exibirInfoSedan(); System.out.println(); popular.exibirInfoPopular(); } Bloco 5. Classe de teste da Fábrica de Carros
  • 23. O segredo do padrão é a representa tanto as primitivas operações que todos os objetos compostos compartilham, tais como operações para acessar e manipular seus filhos. demonstrada na Figura 4, para filhos e composições. Será de fácil compreensão se olharmos a estrutura como uma árvore de cabeça para baixo. Um nó pode ter filhos e também um nó que, por sua vez, pode ter outros filhos e nós. Neste padrão, sendo declaradas em Component classe só deve ter uma responsabilidade, no qual o padrão De acordo com Freeman (2004) Responsabilidade Única e o troca pela transparência. O fato de o cliente lidar uniformemente com os compostos e os nó Contudo, como as operações estão sendo declaradas na classe pouco de segurança, pois um cliente pode tentar fazer algo inadequado ou sem sentido com um elemento. Isto é decisão de projeto; pode direção, separando as responsabilidades em diferentes interfaces. Isto tornaria o projeto seguro, no sentido de que quaisquer chamadas inadequadas de elementos seriam detectadas por ocasião da compilação ou da execução. Poré transparência, e o código necessitaria de usar condicionais e o operador Portanto, esse é um típico caso de que se perde algo para obter algum benefício. Um projetista deve ser guiado pelos princípios de projeto, mas deve f no efeito que eles têm sobre os projetos. Alguma modelagem pode parecer desrespeitar O segredo do padrão é a recursividade devido a uma classe abstrata que representa tanto as primitivas como os seus recipientes. Esta classe abstrata declara operações que todos os objetos compostos compartilham, tais como operações para acessar e manipular seus filhos. Por exemplo, observando a estrutura padrão , a classe Component declara métodos que são utilizados só para filhos e composições. Figura 4. Estrutura padrão do Composite Será de fácil compreensão se olharmos a estrutura como uma árvore de cabeça o. Um nó pode ter filhos e também um nó que, por sua vez, pode ter outros , nota-se que Leaf herda operações de Composite Component. Segundo princípios de orientação a objetos, uma uma responsabilidade, no qual o padrão Composite não respeita. De acordo com Freeman (2004), o padrão abre mão do princípio de projetos da Responsabilidade Única e o troca pela transparência. O fato de o cliente lidar com os compostos e os nós-folha é caracterizado transparência. Contudo, como as operações estão sendo declaradas na classe Component pouco de segurança, pois um cliente pode tentar fazer algo inadequado ou sem sentido com um elemento. Isto é decisão de projeto; pode-se conduzir o processo em outra direção, separando as responsabilidades em diferentes interfaces. Isto tornaria o projeto seguro, no sentido de que quaisquer chamadas inadequadas de elementos seriam detectadas por ocasião da compilação ou da execução. Porém, poderia perder a transparência, e o código necessitaria de usar condicionais e o operador Portanto, esse é um típico caso de que se perde algo para obter algum benefício. deve ser guiado pelos princípios de projeto, mas deve ficar atento sempre no efeito que eles têm sobre os projetos. Alguma modelagem pode parecer desrespeitar 23 uma classe abstrata que como os seus recipientes. Esta classe abstrata declara operações que todos os objetos compostos compartilham, tais como operações para observando a estrutura padrão declara métodos que são utilizados só Será de fácil compreensão se olharmos a estrutura como uma árvore de cabeça o. Um nó pode ter filhos e também um nó que, por sua vez, pode ter outros Composite que estão Segundo princípios de orientação a objetos, uma não respeita. o padrão abre mão do princípio de projetos da Responsabilidade Única e o troca pela transparência. O fato de o cliente lidar é caracterizado transparência. Component, perde-se um pouco de segurança, pois um cliente pode tentar fazer algo inadequado ou sem sentido se conduzir o processo em outra direção, separando as responsabilidades em diferentes interfaces. Isto tornaria o projeto seguro, no sentido de que quaisquer chamadas inadequadas de elementos seriam m, poderia perder a transparência, e o código necessitaria de usar condicionais e o operador instanceof. Portanto, esse é um típico caso de que se perde algo para obter algum benefício. icar atento sempre no efeito que eles têm sobre os projetos. Alguma modelagem pode parecer desrespeitar
  • 24. algum princípio, porém, tudo é uma questão de perspectiva. De acordo com Freeman (2004), talvez pareça incorreto ter operações de gerenciamento de filho mas pode-se deslocar um pouco a perspectiva e ver uma folha como um nó com zero filhos. 4.2.1. Exemplo do Composite Para implementar este tipo de padrão, é (2004) demonstrado na Figura Figura 5 De forma resumida, a classe na composição; implementa comportamento classes, conforme apropriado; declara uma interface para acessar e gerenciar os seus componentes-filhos e defin estrutura recursiva e a implementa. Em composição (um item de menu menu em menu. Na classe filhos; armazena os itens de menu e implementa as operações relacionadas com os filhos presentes na interface de os objetos na composição através da interface de algum princípio, porém, tudo é uma questão de perspectiva. De acordo com Freeman (2004), talvez pareça incorreto ter operações de gerenciamento de filho se deslocar um pouco a perspectiva e ver uma folha como um nó com zero Exemplo do Composite mentar este tipo de padrão, é abordado um exemplo de Freeman Figura 5. 5. Exemplo de implementação do padrão Composite De forma resumida, a classe MenuComponent declara a interface para os objetos na composição; implementa comportamento-padrão para a interface comum a todas a classes, conforme apropriado; declara uma interface para acessar e gerenciar os seus define uma interface para acessar o pai de um componente na estrutura recursiva e a implementa. Em MenuItem, representa objetos um item de menu não tem filhos) e define comportamento para Na classe Menu, define comportamento para componentes que têm itens de menu e implementa as operações relacionadas com os ce de MenuComponent. E Waitress é a classe que manipula os objetos na composição através da interface de MenuComponent. 24 algum princípio, porém, tudo é uma questão de perspectiva. De acordo com Freeman (2004), talvez pareça incorreto ter operações de gerenciamento de filhos nos nós-folha, se deslocar um pouco a perspectiva e ver uma folha como um nó com zero abordado um exemplo de Freeman declara a interface para os objetos padrão para a interface comum a todas as classes, conforme apropriado; declara uma interface para acessar e gerenciar os seus uma interface para acessar o pai de um componente na objetos-folha na comportamento para os itens do , define comportamento para componentes que têm itens de menu e implementa as operações relacionadas com os é a classe que manipula
  • 25. 25 A implementação da classe MenuComponent é demonstrada no Bloco 6. É nítido que esta classe só estabelece o contrato das operações deixando a cargo de suas sub-classes a implementação de cada operação que lhe interessa. Bloco 6. Implementação da classe MenuComponent Em MenuItem, é implementado as operações que dizem respeito aos itens de menu, ou seja, não é possível implementar a operação add, pois não faz sentido um item de menu ter um filho, demonstrado no Bloco 7. As operações referentes a um menu, são implementadas na classe Menu, apresentada no Bloco 9. Menu é do tipo MenuComponent e que, por sua vez, pode ter qualquer quantidade de filhos do tipo MenuComponents. Com a herança mais composição é possível ter a recursividade desejada. Tanto em MenuItem quanto Menu, possuem as mesmas operações, como por exemplo print. Em MenuItem, basta somente imprimir o nome, se é um tipo de comida vegetariana, o preço e a descrição. Já em Menu, a operação print deverá imprimir seu public abstract class MenuComponent{ public void add(MenuComponent menuComponent){ throw new UnsupportedOperationException(); } public void remove(MenuComponent menuComponent){ throw new UnsupportedOperationException(); } public MenuComponent getChild(int i){ throw new UnsupportedOperationException(); } public String getName(){ throw new UnsupportedOperationException(); } public String getDescription(){ throw new UnsupportedOperationException(); } public double getPrice(){ throw new UnsupportedOperationException(); } public boolean isVegetarian(){ throw new UnsupportedOperationException(); } public void print(){ throw new UnsupportedOperationException(); } }
  • 26. 26 nome, descrição e o print implementado em MenuItem. Para que isso seja feito, foi implementado o padrão Iterator. Ele busca todos os métodos print dos objetos do tipo MenuComponent e executa. Bloco 7. Implementação da classe MenuItem A classe que interage com esta estrutura é Waitress e está apresentada no Bloco 8. Ela simplesmente executa o método print. Bloco 8. Implementação da classe Waitress public class Waitress{ MenuComponent allMenus; public Waitress(MenuComponent allMenus){ this.allMenus = allMenus; } public void printMenu(){ allMenus.print(); } } public class MenuItem extends MenuComponent{ String name; String description; boolean vegetarian; double price; public MenuItem(String name, String description, boolean vegetarian, double price){ this.name = name; this.description = description; this.vegetarian = vegetarian; this.price = price; } public String getName(){ return name; } public String getDescription(){ return description; } public double getPrice(){ return price; } public boolean isVegetarian(){ return vegetarian; } public void print(){ System.out.print(" "+getName()); if(isVegetarian()){ System.out.print("(v)"); } System.out.println(", "+getPrice()); System.out.println(" -- "+getDescription()); } }
  • 27. 27 Bloco 9. Implementação da classe MenuItem E por fim, a classe MenuTestDrive mostra um exemplo de como criar um menu raiz e acrescentar seus menus, itens e as recursividades, caso necessário. Veja no Bloco 10. São criados os menus e também o menu raiz denominado allMenus, este objeto representa toda a estrutura hierarquizada. Ao objeto allMenus, são adicionados outros menus, sendo que estes menus serão adicionados itens e, no caso abaixo, o menu dinerMenu possui um sub-menu dessertMenu, e que este possui um item nomeado Apple Pie. Para exibir toda a estrutura é chamado o método print de Waitress. public class MenuItem extends MenuComponent{ import java.util.ArrayList; import java.util.Iterator; public class Menu extends MenuComponent{ ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>(); String name; String description; public Menu(String name, String description){ this.name = name; this.description = description; } public void add(MenuComponent menuComponent){ menuComponents.add(menuComponent); } public void remove(MenuComponent menuComponent){ menuComponents.remove(menuComponent); } public MenuComponent getChild(int i){ return (MenuComponent)menuComponents.get(i); } public String getName(){ return name; } public String getDescription(){ return description; } public void print(){ System.out.print("n"+getName()); System.out.println(", "+getDescription()); System.out.println("---------------------"); Iterator iterator = menuComponents.iterator(); while(iterator.hasNext()){ MenuComponent menuComponent = (MenuComponent)iterator.next(); menuComponent.print(); } } }
  • 28. 28 Bloco 10. Implementação da classe MenuTestDrive Gamma et al.(2000) faz algumas considerações sobre este padrão. • Hierarquias que consistem de objetos primitivos e compostos. Os primitivos podem compor objetos mais complexos, os quais, por suas vez, também podem compor outros objetos, e assim por diante recursivamente. Sempre que o código esperar um objeto primitivo, ele também poderá aceitar um objeto composto. • Torna o cliente simples. Os clientes podem tratar estruturas compostas e objetos individuas de maneira uniforme. Os clientes normalmente não sabem (e não sabem deveriam se preocupar com isto) se estão tratando com uma folha ou um componente composto. Isto simplifica o código a ser escrito nas classes-cliente, porque evita o uso de comandos do tipo CASE com os rótulos classes que definem composição. • Torna mais fácil de acrescentar novas espécies de componentes. Novas subclasses definidas, Composite ou Leaf, funcionam automaticamente com as estruturas existentes e o código do cliente. Os clientes não precisam ser alterados para tratar novas classes Component. • Pode tornar o projeto excessivamente genérico. A desvantagem de facilitar o acréscimo de novos componentes é que isso torna mais difícil restringir os componentes de uma composição. Algumas vezes, é public class MenuTestDrive{ public static void main(String args[]){ MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU","Breakfast"); MenuComponent dinerMenu = new Menu("DINER MENU","Lunch"); MenuComponent cafeMenu = new Menu("CAFÉ MENU","Dinner"); MenuComponent dessertMenu = new Menu("DESSERT MENU","Dessert of course!"); MenuComponent allMenus = new Menu("ALL MENUS","All menus combined"); allMenus.add(pancakeHouseMenu); allMenus.add(dinerMenu); allMenus.add(cafeMenu); dinerMenu.add(new MenuItem("Pasta","Spaghetti with Marinara Sauce, and a slice of sourdough bread",true,3.89)); dinerMenu.add(dessertMenu); dessertMenu.add(new MenuItem("Apple Pie","Apple pie with a flakey crust, topped with vanilla ice cream",true,1.59)); Waitress waitress = new Waitress(allMenus); waitress.printMenu(); } }
  • 29. desejável que uma composição tenha somente certos componentes. Com Composite, não pode confiar no sistema de tipos para garantir a obediência a essas restrições. Ao invés disso, deve teste em tempo d 4.3. DECORATOR Este padrão, de forma dinâmica, agrega valores adicionais em qualquer objeto. Fornece alternativa flexível no uso de subclasses para estender funcionalidades. De acordo com Gamma responsabilidades a objetos individuais dinamicamente e sem afetar outros objetos. Outra característica é que essas responsabilidades pode de alguma forma, desempenho ou estrutura. Decorar objetos é muito comum quando não se quer te subclasses. Por exemplo, havendo a necessidade de combinar responsabilidades entre classes em um total de 6, i diferentes. Segundo Freeman (2004), q subclasses, este comportament Todas as subclasses devem herdar o mesmo comportamento. Contudo, por meio da composição será possível esten tempo de execução. O padrão segue a seguinte desejável que uma composição tenha somente certos componentes. Com , não pode confiar no sistema de tipos para garantir a obediência a essas restrições. Ao invés disso, deve-se usar verificações e teste em tempo de execução. DECORATOR Este padrão, de forma dinâmica, agrega valores adicionais em qualquer objeto. Fornece alternativa flexível no uso de subclasses para estender funcionalidades. Gamma et al. (2000), o uso do Decorator acrescenta bilidades a objetos individuais dinamicamente e sem afetar outros objetos. Outra característica é que essas responsabilidades podem ser removidas sem prejudicar, de alguma forma, desempenho ou estrutura. Decorar objetos é muito comum quando não se quer ter uma explosão de subclasses. Por exemplo, havendo a necessidade de combinar responsabilidades entre classes em um total de 6, isso acarretará numa explosão de 40 combinações Segundo Freeman (2004), quando há herança de um comportamento por meio de subclasses, este comportamento é definido estaticamente no tempo de compilação. Todas as subclasses devem herdar o mesmo comportamento. Contudo, por meio da composição será possível estender o comportamento do objeto de forma dinâmica seguinte estrutura: Figura 6. Estrutura do padrão Decorator 29 desejável que uma composição tenha somente certos componentes. Com , não pode confiar no sistema de tipos para garantir a se usar verificações e Este padrão, de forma dinâmica, agrega valores adicionais em qualquer objeto. Fornece alternativa flexível no uso de subclasses para estender funcionalidades. uso do Decorator acrescenta bilidades a objetos individuais dinamicamente e sem afetar outros objetos. ser removidas sem prejudicar, r uma explosão de subclasses. Por exemplo, havendo a necessidade de combinar responsabilidades entre 3 combinações de classes amento por meio de é definido estaticamente no tempo de compilação. Todas as subclasses devem herdar o mesmo comportamento. Contudo, por meio da forma dinâmica e em
  • 30. A classe Component responsabilidades acresce define um objeto para o qual responsabilidades adicionais podem ser atribuídas; a classe Decorator mantém uma referência para um objeto que segue a interface de Component ao componente. 4.3.1. Exemplo do Decorator Freeman (2004) apresenta mostrado na figura 5. Beverage é uma classe abstrata de componente. sozinha ou englobada por um decorador. componentes concretos que são um tipo de bebida. Esses objetos CondimentDecorator “tem CondimentDecorator tem uma variável de instância que co bebida. Mocha, Whip e Soy Beverage. Os decoradores podem adicionar novos métodos; no entanto, o novo comportamento geralmente é adicionado fazendo cálculo antes e depois de um método existente no componente. Eles precisam implementar não somente getDescription(). Figura 7 Component define a interface para objetos que podem ter ntadas aos mesmos dinamicamente; Concre define um objeto para o qual responsabilidades adicionais podem ser atribuídas; a classe mantém uma referência para um objeto Component e define uma interface Component e ConcreteDecorator acrescenta responsabi Exemplo do Decorator apresenta um exemplo de aplicação do padrão decorator é uma classe abstrata de componente. Cada bebida por um decorador. Expresso, DarkRoast e HouseBlend componentes concretos que estendem de Beverage no que caracteriza que essas classes Esses objetos receberão dinamicamente novos comportamentos. “tem-uma” (engloba) uma bebida, o que si tem uma variável de instância que contém uma referência a uma Soy são os decoradores e eles pode estender o estado de es podem adicionar novos métodos; no entanto, o novo mento geralmente é adicionado fazendo cálculo antes e depois de um método Eles precisam implementar não somente cost() 7. Exemplo de implementação do padrão Decorator 30 define a interface para objetos que podem ter ConcretComponent define um objeto para o qual responsabilidades adicionais podem ser atribuídas; a classe e define uma interface acrescenta responsabilidades padrão decorator pode ser usada HouseBlend são no que caracteriza que essas classes receberão dinamicamente novos comportamentos. ” (engloba) uma bebida, o que significa que o ntém uma referência a uma são os decoradores e eles pode estender o estado de es podem adicionar novos métodos; no entanto, o novo mento geralmente é adicionado fazendo cálculo antes e depois de um método cost(), mas também
  • 31. 31 No bloco abaixo, segue o código para implementação da classe Beverage e suas subclasses. Bloco 11. Implementação da classe Beverage A classe CondimentDecorator simplesmente repassa as solicitações de descrições para a bebida e suas subclasses estendem essa operação. O código é mostrado no bloco abaixo. public abstract class Beverage{ String description = "Unknown Beverage"; public String getDescription(){ return description; } public abstract double cost(); } public class Expresso extends Beverage{ public Expresso(){ description = "Expresso"; } public double cost(){ return 1.99; } } public class HouseBlend extends Beverage{ public HouseBlend(){ description = "House Blend Coffee"; } public double cost(){ return 0.89; } } public class DarkRoast extends Beverage{ public DarkRoast(){ description = "Dark Roast"; } public double cost(){ return 1.05; } }
  • 32. 32 Bloco 12. Implementação das classes dos condimentos Com o padrão Decorator tornam-se fácil acrescentar os condimentos as bebidas de forma dinâmica. Assim, não é preciso estabelecer que cada bebida possa ter apenas um condimento, ou combinações de dois. Por exemplo, Expresso pode ter o condimento Whip e também Whip com Soy ou até os três. Com uma pequena quantidade pode public abstract class CondimentDecorator extends Beverage{ public abstract String getDescription(); } public class Soy extends CondimentDecorator{ Beverage beverage; public Soy(Beverage beverage){ this.beverage = beverage; } public String getDescription(){ return beverage.getDescription()+ ", Soy"; } public double cost(){ return 0.15 + beverage.cost(); } } public class Whip extends CondimentDecorator{ Beverage beverage; public Whip(Beverage beverage){ this.beverage = beverage; } public String getDescription(){ return beverage.getDescription()+", Whip"; } public double cost(){ return 0.10 + beverage.cost(); } } public class Mocha extends CondimentDecorator{ Beverage beverage; public Mocha(Beverage beverage){ this.beverage = beverage; } public String getDescription(){ return beverage.getDescription() + ", Mocha"; } public double cost(){ return 0.20 + beverage.cost(); } }
  • 33. 33 parecer fácil, mas se tivesse 20 condimentos para 10 tipos de bebidas ficaria difícil de criar cada classe representando uma bebida com combinações de condimentos. A atribuição de comportamentos em tempo de execução é apresentada no seguinte bloco. Bloco 13. Implementação da classe StarbuzzCoffee No objeto beverage é simplesmente instanciado o objeto Expresso sem nenhum condimento. Seu preço final será de R$ 1.99. Em beverage2, é instanciado o objeto DarkRoast e é acrescentado 3 tipos de condimentos: Mocha, Soy e Whip. Para que beverage2 contenha os condimentos é preciso instanciá-los e passar o tipo da bebida como parâmetro, formando uma espécie de invólucro. Mocha envolve beverage2, assim como Soy e Whip da mesma forma. A descrição da bebida retornará “Dark Roast, Mocha, Soy, Whip” e o preço final (somando o custo da bebida mais os condimentos) de R$ 1,50. De igual modo beverage3 recebe um condimento e a descrição e o preço são alterados. 4.4. CHAIN OF RESPONSIBILITY O Chain of Responsability (Cadeia de Responsabilidades) é um tipo de padrão comportamental e, segundo Gamma et al. (2000), a intenção do padrão é evitar o acoplamento do remetente de uma solicitação ao seu receptor, ao dar a mais de um objeto a oportunidade de tratar a solicitação. Encadear os objetos receptores, passando a solicitação ao longo da cadeia até que um objeto a trate. Na Figura 8 está demonstrada a public class StarbuzzCoffee{ public static void main(String args[]){ Beverage beverage = new Expresso(); System.out.println(beverage.getDescription()+" R$"+beverage.cost()); Beverage beverage2 = new DarkRoast(); beverage2 = new Mocha(beverage2); beverage2 = new Soy(beverage2); beverage2 = new Whip(beverage2); System.out.println(beverage2.getDescription()+" R$"+beverage2.cost()); Beverage beverage3 = new HouseBlend(); beverage3 = new Mocha(beverage3); System.out.println(beverage3.getDescription()+" R$"+beverage3.cost()); } }
  • 34. estrutura básica do padrão. A class e opcionalmente implementa o elo ( solicitações pelas quais é responsável podendo também acessar seu sucessor e se o ConcreteHandler pode tratar a solicitação para o seu sucessor. Por fim, a classe objeto ConcreteHandler da cadeia, (GAMMA et al., 2000). O efeito que se dá quando um cliente emite uma solic longo da cadeia até que um objeto la. Figura 4.4.1. Exemplo do Chain of Responsability Para exemplificar, é abordado uma operação efetuar pagamento entre os bancos. Para iniciar, criar- sistema, exibido no Bloco 14 Bloco A classe BancoChain responsabilidades. Ela possui um atributo que é o ident referência para o próximo objeto. O método e faz verifica se o próximo for nulo, então o próximo na corrente será o parâmetro; caso public enum IDBancos { bancoA, bancoB, bancoC, bancoD } drão. A class Handler define uma interface para tratar solicitações e opcionalmente implementa o elo (link) ao sucessor. ConcreteHandle solicitações pelas quais é responsável podendo também acessar seu sucessor e se o pode tratar a solicitação, ele assim o faz; caso contrário, ele repassa a solicitação para o seu sucessor. Por fim, a classe Client inicia a solicitação para um da cadeia, (GAMMA et al., 2000). O efeito que se dá quando um cliente emite uma solicitação, esta se propaga ao longo da cadeia até que um objeto ConcreteHandler assuma a responsabilidade de tratá Figura 8. Estrutura do Chain of Responsability Exemplo do Chain of Responsability Para exemplificar, é abordado um exemplo de Brizeno (2011) que implementa uma operação efetuar pagamento entre os bancos. -se uma enumeração que identificará os bancos utilizado no 14. Bloco 14. Implementação da enumeração de IDBancos BancoChain , exibida no Bloco 15, implementará a cadeia de responsabilidades. Ela possui um atributo que é o identificador do banco e outro a referência para o próximo objeto. O método setNext recebe uma nova instância da classe e faz verifica se o próximo for nulo, então o próximo na corrente será o parâmetro; caso bancoA, bancoB, bancoC, bancoD 34 define uma interface para tratar solicitações ConcreteHandle trata de solicitações pelas quais é responsável podendo também acessar seu sucessor e se o solicitação, ele assim o faz; caso contrário, ele repassa a inicia a solicitação para um itação, esta se propaga ao assuma a responsabilidade de tratá- um exemplo de Brizeno (2011) que implementa que identificará os bancos utilizado no implementará a cadeia de ificador do banco e outro a recebe uma nova instância da classe e faz verifica se o próximo for nulo, então o próximo na corrente será o parâmetro; caso
  • 35. 35 contrário, repassa esta responsabilidade para o próximo elemento. Então, a instância que deve ser adicionada na corrente irá percorrer os elementos até chegar ao último. O algoritmo de pagamento é verificar se o banco atual pode fazer o pagamento. Para isto é utilizado o identificador do banco, que é comparado com o identificador passado por parâmetro. Se o elemento atual puder responder a requisição é chamado o método que vai efetuar o pagamento de fato. Este método é abstrato, e as subclasses devem implementá-lo, com seu próprio mecanismo. Se o elemento atual não puder responder, ele repassa a chamado ao próximo elemento da lista. Antes disto é feita uma verificação, por questões de segurança, se este próximo elemento realmente existe. Caso nenhum elemento possa responder, é disparada uma exceção. Bloco 15. Implementação da classe BancoChain public enum IDBancos { public abstract class BancoChain { protected BancoChain next; protected IDBancos identificadorDoBanco; public BancoChain(IDBancos id) { next = null; identificadorDoBanco = id; } public void setNext(BancoChain forma) { if (next == null) { next = forma; } else { next.setNext(forma); } } public void efetuarPagamento(IDBancos id) throws Exception { if (podeEfetuarPagamento(id)) { efetuaPagamento(); } else { if (next == null) { throw new Exception("banco não cadastrado"); } next.efetuarPagamento(id); } } private boolean podeEfetuarPagamento(IDBancos id) { if (identificadorDoBanco == id) { return true; } return false; } protected abstract void efetuaPagamento(); }
  • 36. 36 Definida a estrutura da cadeia de responsabilidades, implementa-se um banco concreto, que corresponde a uma chamada. O BancoA inicializa seu ID e, no método de efetuar o pagamento, exibe no terminal que o pagamento foi efetuado. A implementação dos ostros bancos segue este exemplo, exibida no Bloco 16 abaixo. Bloco 16. Implementação do banco concreto Sendo assim, cada banco chama seu método efetuarPagamento de acordo com a cadeia de responsabilidades criada, de acordo com o bloco abaixo. Bloco 17. Implemantação do padrão Chain of Responsability O diagrama de classes deste exemplo mostrado na Figura 9. public static void main(String[] args) { BancoChain bancos = new BancoA(); bancos.setNext(new BancoB()); bancos.setNext(new BancoC()); bancos.setNext(new BancoD()); try { bancos.efetuarPagamento(IDBancos.bancoC); bancos.efetuarPagamento(IDBancos.bancoD); bancos.efetuarPagamento(IDBancos.bancoA); bancos.efetuarPagamento(IDBancos.bancoB); } catch (Exception e) { e.printStackTrace(); } } public class BancoA extends BancoChain { public BancoA() { super(IDBancos.bancoA); } @Override protected void efetuaPagamento() { System.out.println("Pagamento efetuado no banco A"); } }
  • 37. Figura 9. Diagrama de classes do exemplo do padrão Chain of Responsability Gamma et al. (2000), dest • Acoplamento reduzido qual o outro objeto que trata de uma solicitação. Um objeto tem que saber somente que uma solicitação será tratada "apropriadamente" Tanto o receptor como o remetente não conhecimento explícito um do outro, e um objeto que está na cadeia não necessita conhecer a estrutura da mesma. • Flexibilidade adicional na atribuição de responsabilidades a objetos Chain of Responsability dá uma flex responsabilidades entre objetos. É possível acrescentar ou mudar responsabilidades para o tratamento de uma solicitação pelo acréscimo ou mudança da cadeia em tempo de execução. Pode com subclasses pa • A recepção não é garantida receptor explícito, não há pode sair pelo final da cadeia sem ter sido tratada. Uma solicitação também pode não ser tratada quando a cadeia não está configurada apropriadamente. 4.5. OBSERVER O padrão Observer Subscribe, define uma dependência um . Diagrama de classes do exemplo do padrão Chain of Responsability Gamma et al. (2000), destaca alguns benefícios e deficiências deste padrão. Acoplamento reduzido: o padrão libera um objeto de ter que conhecer qual o outro objeto que trata de uma solicitação. Um objeto tem que saber somente que uma solicitação será tratada "apropriadamente" anto o receptor como o remetente não conhecimento explícito um do outro, e um objeto que está na cadeia não necessita conhecer a estrutura Flexibilidade adicional na atribuição de responsabilidades a objetos Chain of Responsability dá uma flexibilidade adicional na distribuição de responsabilidades entre objetos. É possível acrescentar ou mudar responsabilidades para o tratamento de uma solicitação pelo acréscimo ou mudança da cadeia em tempo de execução. Pode-se combinar isto com subclasses para especializar estaticamente os handlers A recepção não é garantida. Uma vez que uma solicitação não tem um receptor explícito, não há garantia de que ela será tratada pode sair pelo final da cadeia sem ter sido tratada. Uma solicitação também pode não ser tratada quando a cadeia não está configurada apropriadamente. O padrão Observer, também conhecido como Dependents ou Publish efine uma dependência um-para-muitos entre objetos de forma que quando 37 . Diagrama de classes do exemplo do padrão Chain of Responsability aca alguns benefícios e deficiências deste padrão. um objeto de ter que conhecer qual o outro objeto que trata de uma solicitação. Um objeto tem que saber somente que uma solicitação será tratada "apropriadamente" . anto o receptor como o remetente não conhecimento explícito um do outro, e um objeto que está na cadeia não necessita conhecer a estrutura Flexibilidade adicional na atribuição de responsabilidades a objetos. O ibilidade adicional na distribuição de responsabilidades entre objetos. É possível acrescentar ou mudar responsabilidades para o tratamento de uma solicitação pelo acréscimo se combinar isto handlers. . Uma vez que uma solicitação não tem um de que ela será tratada - a solicitação pode sair pelo final da cadeia sem ter sido tratada. Uma solicitação também pode não ser tratada quando a cadeia não está configurada , também conhecido como Dependents ou Publish- muitos entre objetos de forma que quando
  • 38. 38 um objeto mudar de estado, todos os seus dependentes sejam notificados e atualizados automaticamente (GAMMA et al., 2000). No Observer quando um estado de um objeto é alterado, todos os seus dependentes são notificados, e dependendo do tipo de notificação o observador também pode ser atualizado com novos valores (FREEMAN et al., 2004). Observer desacopla um objeto do conhecimento de que outros objetos dependem dele (ROCHA, 2003). Existem algumas maneiras diferentes de se implementar o padrão Observer, mas a maioria inclui as interfaces Subject e Observer. Um subject pode ter um número qualquer de observadores dependentes, e todos os observadores são notificados quando subject sofre uma mudança de estado, assim em resposta, cada observador inquirirá o subject para sincronizar o seu estado com o estado do subject (GAMMA et al., 2000). Esta iteração é o que GAMMA et al. (2000) chama de publish-subscribe, onde o subject é o publicador de notificações e as envia sem ter que saber quem são os seus observadores, lembrando que um número qualquer de observadores podem se inscrever para receber essas notificações, nota-se então que existe uma relação entre um subject e muitos observadores (1:N). Como o sujeito é o único proprietário dos dados, os observadores dependem do sujeito para alterá-los quando os dados são alterados, o que leva a um design orientado a objetos mais simples do que permitir que muitos objetos controlem os mesmos dados (FREEMAN et al., 2004). Segundo Gamma et al. (2000), este padrão deve ser aplicado: • Quando uma abstração tem dois aspectos, um dependente do outro. Encapsulam-se esses aspectos separadamente para que assim permita-se variá-los e reutizá-los independentemente. • Quando uma mudança em um objeto exige mudanças em outros objetos, e não sabe-se quantos objetos necessitam ser mudados. • Quando não deseja-se que objetos sejam fortemente acoplados. O padrão Observer fornece um design de objeto onde os sujeitos e os observadores são levemente ligados, ou seja, os objetos podem interagir, mas sabem muito pouco um do outro, o que trona mais fácil lidar com mudanças, já que minimizam a interdependência entre os objetos (FREEMAN et al., 2004). Isso porque a única coisa que o sujeito sabe sobre um observador é que ele implementa uma certa interface
  • 39. (Observer), com isso podemos adicionar novos observadores a qualquer momento, nunca precisaremos modificar o sujeito para adicionar novos tipos de observadores e ainda podemos reutilizar sujeitos ou observadores independentemente uns dos outros (FREEMAN et al., 2004). Segundo o Rocha padrões centrada no padrão Observer o View é o Observer para o pelo usuário e lê dados encapsulando lógica de controle que afeta o A figura 10 mostra a estrutura do padrão Observer. Figura 10 Os participantes dessa estrutura são explicitados segundo Gamma e Freeman et al. (2004): • Subject – objetos Observer pode observar um subject. Os objetos usam esta interface para se regi removidos. • Observer – deveriam ser notificados sobre mudanças em um subject. Todos os observadores potenciais precisam implementar essa interface. demos adicionar novos observadores a qualquer momento, nunca precisaremos modificar o sujeito para adicionar novos tipos de observadores e ainda podemos reutilizar sujeitos ou observadores independentemente uns dos outros (2003) o padrão de arquitetura MVC é uma combinação de padrões centrada no padrão Observer, onde o Model notifica o View sobre as alterações; é o Observer para o Model e notifica o Controller sobre os eventos iniciados pelo usuário e lê dados do Model; e o Controller é um Observer para o encapsulando lógica de controle que afeta o Model e seleciona View. mostra a estrutura do padrão Observer. . Estrutura do padrão Observer (GAMMA et al, 2000). Os participantes dessa estrutura são explicitados segundo Gamma conhece os seus observadores. Um número qualquer de objetos Observer pode observar um subject. Os objetos usam esta interface para se registrarem como observadores e para serem removidos. – define uma interface de atualização para objetos que deveriam ser notificados sobre mudanças em um subject. Todos os observadores potenciais precisam implementar essa interface. 39 demos adicionar novos observadores a qualquer momento, nunca precisaremos modificar o sujeito para adicionar novos tipos de observadores e ainda podemos reutilizar sujeitos ou observadores independentemente uns dos outros padrão de arquitetura MVC é uma combinação de sobre as alterações; sobre os eventos iniciados é um Observer para o View, Os participantes dessa estrutura são explicitados segundo Gamma et al. (2000) conhece os seus observadores. Um número qualquer de objetos Observer pode observar um subject. Os objetos usam esta strarem como observadores e para serem define uma interface de atualização para objetos que deveriam ser notificados sobre mudanças em um subject. Todos os observadores potenciais precisam implementar essa interface.
  • 40. • ConcreteSubject ConcreteObserver. Envia uma notificação para os seus observadores quando seu estado muda. • ConcreteObserver que implemente a interface Observer. Mantém uma referênc objeto ConcreteSubject, também armazena estados que deveriam permanecer consistentes com os do Subject. Implementa a interface de atualização de Observer, para manter seu estado consistente com o do subject. O ConcreteSubject notifica seus obser mudança que poderia tornar inconsistente o estado deles com o seu próprio et al., 2000). A figura 11 apresenta um diagrama de sequencia de como as colaborações acontecem entre um subject e dois observadores. Figura 11. Diagrama de sequência entre um subject e dois observadores (GAMMA et al, 2000). O objeto Observer na figura xxx que inicia a solicitação de mudança posterga sua atualização até que consiga uma notificação do subject. Notify nã chamada pelo subject, pode ser chamada por um observador ou por um outro tipo de objeto (GAMMA et al., 2000). As conseqüências (benefícios e deficiências) da utilização desse padrão apontadas por Gamma et al. (2000) são: permite acrescentar obse modificar o subject ou outros observadores; permite variar subjects e observadores de forma independente; acoplamento abstrato entre Subject e ConcreteSubject – armazena estados de interesse para objetos ConcreteObserver. Envia uma notificação para os seus observadores quando seu estado muda. ConcreteObserver – os ConcreteObservers podem ser qualquer classe que implemente a interface Observer. Mantém uma referênc objeto ConcreteSubject, também armazena estados que deveriam permanecer consistentes com os do Subject. Implementa a interface de atualização de Observer, para manter seu estado consistente com o do O ConcreteSubject notifica seus observadores sempre que ocorrer uma mudança que poderia tornar inconsistente o estado deles com o seu próprio apresenta um diagrama de sequencia de como as colaborações acontecem entre um subject e dois observadores. . Diagrama de sequência entre um subject e dois observadores (GAMMA et al, 2000). O objeto Observer na figura xxx que inicia a solicitação de mudança posterga sua atualização até que consiga uma notificação do subject. Notify nã chamada pelo subject, pode ser chamada por um observador ou por um outro tipo de ., 2000). As conseqüências (benefícios e deficiências) da utilização desse padrão apontadas por Gamma et al. (2000) são: permite acrescentar obse modificar o subject ou outros observadores; permite variar subjects e observadores de forma independente; acoplamento abstrato entre Subject e Observer, e por não serem 40 armazena estados de interesse para objetos ConcreteObserver. Envia uma notificação para os seus observadores os ConcreteObservers podem ser qualquer classe que implemente a interface Observer. Mantém uma referência para um objeto ConcreteSubject, também armazena estados que deveriam permanecer consistentes com os do Subject. Implementa a interface de atualização de Observer, para manter seu estado consistente com o do vadores sempre que ocorrer uma mudança que poderia tornar inconsistente o estado deles com o seu próprio (GAMMA apresenta um diagrama de sequencia de como as colaborações . Diagrama de sequência entre um subject e dois observadores (GAMMA et al, 2000). O objeto Observer na figura xxx que inicia a solicitação de mudança posterga sua atualização até que consiga uma notificação do subject. Notify não é sempre chamada pelo subject, pode ser chamada por um observador ou por um outro tipo de As conseqüências (benefícios e deficiências) da utilização desse padrão apontadas por Gamma et al. (2000) são: permite acrescentar observadores sem modificar o subject ou outros observadores; permite variar subjects e observadores de Observer, e por não serem
  • 41. fortemente acoplados os mesmos podem pertencer a diferentes camadas de abs suporte a comunicações broadcast sem especificar seu receptor; atualizações inesperadas, pois como um observador não conhece a presença dos outros, eles podem ser cegos para o custo global de mudança. Os padrões relacionados são Mediator, encapsula atualizações complexas, onde o ChangeManager atua como um mediador entre subjects e observadores, e o Singleton onde o ChangeManager pode usar o Singleton para torná lo único e globalmente acessível. 4.5.1. Exemplo de Observer Para exemplificar o padrão Observer (2004), incluindo a base da explicação sobre o exemplo construção de uma estação meteorológica baseada na Internet, que deverá monitorar as condições atuais do tempo (te aplicativo que forneça as condições atuais, estatísticas meteorológicas e uma simples previsão. A figura 12 apresenta o diagrama de classes que será utilizado no exemplo Figura fortemente acoplados os mesmos podem pertencer a diferentes camadas de abs suporte a comunicações broadcast sem especificar seu receptor; atualizações inesperadas, pois como um observador não conhece a presença dos outros, eles podem ser cegos para o custo global de mudança. Os padrões relacionados são Mediator, encapsulando a semântica de atualizações complexas, onde o ChangeManager atua como um mediador entre subjects e observadores, e o Singleton onde o ChangeManager pode usar o Singleton para torná lo único e globalmente acessível. Exemplo de Observer car o padrão Observer utilizou-se um exemplo de , incluindo a base da explicação sobre o exemplo. O exemplo baseia construção de uma estação meteorológica baseada na Internet, que deverá monitorar as condições atuais do tempo (temperatura, umidade e pressão). A ideia é criar que forneça as condições atuais, estatísticas meteorológicas e uma simples apresenta o diagrama de classes que será utilizado no exemplo Figura 12. Diagrama de classes da estação meteorológica 41 fortemente acoplados os mesmos podem pertencer a diferentes camadas de abstração; suporte a comunicações broadcast sem especificar seu receptor; atualizações inesperadas, pois como um observador não conhece a presença dos outros, eles podem ndo a semântica de atualizações complexas, onde o ChangeManager atua como um mediador entre subjects e observadores, e o Singleton onde o ChangeManager pode usar o Singleton para torná- um exemplo de Freeman et al. O exemplo baseia-se na construção de uma estação meteorológica baseada na Internet, que deverá monitorar as mperatura, umidade e pressão). A ideia é criar um que forneça as condições atuais, estatísticas meteorológicas e uma simples apresenta o diagrama de classes que será utilizado no exemplo.
  • 42. 42 De acordo com o diagrama de classe todos os componentes meteorológicos implementam a interface Observer, o que dá a Subject uma interface comum com a qual falar na hora de atualizar os observadores, e a interface DisplayElement deve ser implementada por todos os elementos de exibição. As interfaces utilizadas são mostradas no bloco 18. Na interface Subject temos um método para registro e outro para exclusão de um elemento, que utilizam um Observer como argumento. A interface Observer possue o método update recebe os valores de estado do Subject quando uma medição muda. Essa interface é implementada por todos os observadores. A interface DisplayElement possui apenas o método display() que é chamado quando o elemento de exibição precisar ser exibido. A classe WeatherData monitora os dados vindos de Estação Meteorológica e atualiza as exibições. O objeto WeatherData sabe como falar com a estação e obter os dados atualizados de temperatura, umidade de pressão. O método measurementsChanged() é chamado sempre que dados de medição estão disponíveis. O bloco 19 mostra a classe WeatherData. Essa classe implementa a interface Subject e adiciona uma lista para conter os Observers no método construtor. Como implementamos Subject, os métodos registerObserver(), removeObserver() e notifyObservers() devem ser aplicados, assim para adicionar um observador ele é colocado no final da lista e para remover ele é retirado da lista. No notifyObservers() é onde passamos para todas os observadores sobre o estado. O método public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); } public interface Observer { public void update(float temp, float umidade, float pressao); } public interface DisplayElement { public void display(); } Bloco 18. Interfaces Subject, Observer e DisplayElement
  • 43. 43 measurementsChanged() notifica os Observers quando obtemos medições atualizadas da Estação meteorológica. O método setMeasurements() foi utilizado para testar os elementos de exibição. Após isso, é hora de construir os elementos de exibição: exibição das condições atuais, exibição das estatísticas e exibição da previsão. Todas as classes que farão essas exibições devem implementar Observer e DisplayElement, nesse exemplo public class WeatherData implements Subject{ private ArrayList observers; private float temperatura; private float umidade; private float pressao; public WeatherData(){ observers = new ArrayList(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removeObserver(Observer o) { int i = observers.indexOf(o); if (i >= 0){ observers.remove(i); } } @Override public void notifyObservers() { for (int i = 0; i < observers.size(); i++) { Observer observer = (Observer) observers.get(i); observer.update(temperatura, umidade, pressao); } } public void measurementsChanged() { notifyObservers(); } public void setMeasurements(float temperatura, float umidade, float pressao){ this.temperatura = temperatura; this.umidade = umidade; this.pressao = pressao; measurementsChanged(); } Bloco 19. Classe WeatherData
  • 44. 44 mostra-se apenas a implementação da exibição das condições atuais, pois as outras seguem um formato parecido. O bloco 20 apresenta essa implementação. A classe CurrentConditionsDisplay deve receber o objeto WeatherData (o Subject) para registrar a exibição como um observador. O método display() imprimi apenas a temperatura e a umidade mais recentes. A classe de teste deverá criar o objeto WeatherData e as três exibições que serão passadas para WeatherData, conforme bloco 21. WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); //mostrar algumas estatísticas ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); //previsão de acordo com a pressão public class CurrentConditionsDisplay implements Observer, DisplayElement { private float temperatura; private float umidade; private Subject weatherData; public CurrentConditionsDisplay(Subject weatherData){ this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void update(float temperatura, float umidade, float pressao) { this.temperatura = temperatura; this.umidade = umidade; display(); } @Override public void display() { System.out.println("Condições atuais: " + temperatura + "C graus e " + umidade + "% umidade"); } } Bloco 20. Implemnetação das interfaces Observer e DisplayElement em CurrentConditionDisplay. Bloco 21. Criação do objeto weatherData e as 3 exibições
  • 45. 45 Nesse exemplo criamos o um exemplo do padrão Observer, porém se utilizarmos Java, há a opção de contar com o suporte interno ao padrão Observer dele, assim tudo que teríamos que fazer é estender Observable e informá-lo quando notificar os Observadores, pois a API faria o resto. 4.6. STRATEGY O padrão Strategy, também conhecido como Policy, define uma família de algoritmos, encapsula cada um deles e os torna intercambiáveis, assim a estratégia deixa o algoritmo varias independentemente dos clientes que o utilizam (GAMMA et al., 2000). Strategy sugere que algoritmos parecidos sejam separados de quem os utiliza (BRIZENO, 2011). Devemos separar o que muda do que fica igual (FREEMAN et al., 2004). O padrão também apresenta facilidade para extensão das funcionalidades e nenhuma outra parte do código precisa ser alterada. Nesse padrão as classes de estratégia são chamadas de Comportamento e a classe que utiliza o comportamento é chamada de Contexto, ou seja, para um determinado Contexto pode-se aplicar um conjunto de comportamentos (BRIZENO, 2011). Segundo Gamma et al. (2000), o padrão Strategy se aplica quando: • Muitas classes relacionadas diferem somente no seu comportamento. • Necessita-se de variantes de um algoritmo. As estratégias podem ser usadas quando essas variantes são implementadas como uma hierarquia de classes de algoritmos. • Um algoritmo usa dados dos quais os clientes não deveriam ter conhecimento. • Uma classe define muitos comportamentos, e estes aparecem em suas operações como múltiplos comandos condicionais da linguagem. Strategy usa composição. Usar composição dá mais flexibilidade e permite encapsular uma família de algoritmos em seu próprio conjunto de classes, além disso permite alterar o comportamento no tempo de execução, desde o objeto com o qual estiver compondo implemente a interface de comportamento certa (FREEMAN et al., 2004). A composição é usada em outros padrões de projetos além do Strategy. A figura 13 apresenta a estrutura do padrão Strategy.
  • 46. Figura 13 Os participantes dessa estrutura são explicitados segundo Gamma • Strategy – suportados, e o Context usa esta interface para chamar o algoritmo definido por uma ConcreteStrategy. • ConcreteStrategy Strategy. • Context – uma referência para um objeto Strategy. Pode definir uma interface que permite a Strategy acessar seus dados. Strategy e Context interagem para i disso um contexto repassa solicitações dos seus clientes para sua estratégia (GAMMA et al., 2000). A chave para aplicação do padrão Strategy é projetar, para a estratégia e seu contexto, interfaces genéricas o bastant (GAMMA et al., 2000). Como consequências, entre benefícios e desvantagens, Gamma aponta: famílias de algoritmos relacionadas; uma alternativa ao uso de subclasses; eliminam comandos condicionais da l escolha de implementações, fornecendo diferentes implementações do mesmo comportamento; os clientes devem conhecer diferentes podem ser expostos a detalhes e aspectos de implementação; entre Strategy e Context pode ser um problema; aumento do número de objetos. Quando outra pessoa está utilizando seu código ela pode escolher qualquer comportamento para o contexto que ela deseja aplicar, o que 13. Estrutura do Padrão Strategy (GAMMA et al., 2000). s dessa estrutura são explicitados segundo Gamma – define uma interface comum para todos os algoritmos suportados, e o Context usa esta interface para chamar o algoritmo definido por uma ConcreteStrategy. ConcreteStrategy – implementa o algoritmo usando a interface de é configurado com um objeto ConcreteStrategy e mantém uma referência para um objeto Strategy. Pode definir uma interface que permite a Strategy acessar seus dados. Strategy e Context interagem para implementar o algoritmo escolhido, além disso um contexto repassa solicitações dos seus clientes para sua estratégia (GAMMA A chave para aplicação do padrão Strategy é projetar, para a estratégia e seu contexto, interfaces genéricas o bastante para suportar uma variedade de algoritmos Como consequências, entre benefícios e desvantagens, Gamma aponta: famílias de algoritmos relacionadas; uma alternativa ao uso de subclasses; eliminam comandos condicionais da linguagem de programação; possibilidade de escolha de implementações, fornecendo diferentes implementações do mesmo comportamento; os clientes devem conhecer diferentes Strategies, assim os clientes podem ser expostos a detalhes e aspectos de implementação; custo de comunicação entre Strategy e Context pode ser um problema; aumento do número de objetos. Quando outra pessoa está utilizando seu código ela pode escolher qualquer contexto que ela deseja aplicar, o que pode ser visto como um 46 s dessa estrutura são explicitados segundo Gamma et al. (2000). define uma interface comum para todos os algoritmos suportados, e o Context usa esta interface para chamar o algoritmo ta o algoritmo usando a interface de é configurado com um objeto ConcreteStrategy e mantém uma referência para um objeto Strategy. Pode definir uma interface que mplementar o algoritmo escolhido, além disso um contexto repassa solicitações dos seus clientes para sua estratégia (GAMMA A chave para aplicação do padrão Strategy é projetar, para a estratégia e e para suportar uma variedade de algoritmos Como consequências, entre benefícios e desvantagens, Gamma et al (2000) aponta: famílias de algoritmos relacionadas; uma alternativa ao uso de subclasses; inguagem de programação; possibilidade de escolha de implementações, fornecendo diferentes implementações do mesmo , assim os clientes custo de comunicação entre Strategy e Context pode ser um problema; aumento do número de objetos. Quando outra pessoa está utilizando seu código ela pode escolher qualquer pode ser visto como um
  • 47. 47 potencial problema, já que o usuário deve conhecer bem a diferença entre as estratégias para saber escolher qual se aplica melhor ao contexto dele (BRIZENO, 2011). Como padrão relacionado temos o Flyweight, onde objetos Strategy geralmente são bons flyweights (GAMMA et al., 2000). 4.6.1. Exemplo de padrão Strategy Para exemplificar o padrão Strategy, utilizou-se um exemplo apresentado por Brizeno (2011) com suas explicações, onde em uma empresa existe um conjunto de cargos, para cada cargo existem regras de cálculo de imposto e determinada porcentagem do salário deve ser retirada de acordo com o salário base do funcionário. As regras são mostradas a seguir: • O Desenvolvedor deve ter um imposto de 15% caso seu salário seja maior que R$ 2000,00 e 10% caso contrário; • O Gerente deve ter um imposto de 20% caso seu salário seja maior que R$ 3500,00 e 15% caso contrário; • O DBA deve ter um imposto de de 15% caso seu salário seja maior que R$ 2000,00 e 10% caso contrário; O padrão Strategy sugere que os métodos de cálculo de imposto sejam separados do funcionário. Assim devemos encapsular todos os algoritmos da mesma família, ou seja, a família que calcula salários com impostos deve ser separada, e para encapsulá-las cria-se uma interface. O bloco 22 apresenta a criação da interface de calculo do imposto. Após definida a classe que encapsula os algoritmos, as estratégias concretas de calculo do imposto devem ser definidas, assim como Brizeno (2011) definiremos apenas uma das classes de cálculo, pois as outras 2 seguem o mesmo padrão. O Bloco 23 mostra a implementação do imposto de 20% ou 15%. interface CalculaImposto { double calculaSalarioComImposto(Funcionario umFuncionario); } Bloco 22. Interface CalculaImposto