1. “Design Patterns” padrões de projeto
para software Orientados a Objeto
Eduardo M. F. Jorge (emjorge1974@gmail.com)
2. Como tornar projetos mais reutilizáveis, com menos
acoplamento e com um maior nível de reutilização?
Tarefa para desenvolvedores experientes
3. Padrões de Projeto
} O bom desenvolvimento de um software orientado a
objeto depende de alguns fatores:
} Uma boa decomposição do sistema em classes e objetos
} O conhecimento pelos desenvolvedores dos diversos
aspectos ligados à orientação a Objeto:
} Encapsulação
} Reutilização
} Flexibilidade
} Portabilidade
} Desempenho
4. Padrões de Projeto
} Desenvolvedores iniciantes podem utilizar padrões de
projetos catalogados por “experts” para obter
conhecimento e experiência na construção de aplicações
orientadas a objeto.
} Com a boa utilização de padrões de projeto a
comunicação entre desenvolvedores, e a manutenção de
sistemas, tornam-se menos complexas.
} Padrões de projeto podem ajudar a encontrar abstrações
que tornem o software mais flexível e reutilizável.
5. Padrões de Projeto
} A definição clássica para os Designs Patterns é a seguinte:
"um Pattern descreve um problema que se repete várias vezes
em um determinado meio, e em seguida descreve o núcleo da
sua solução, de modo que esta solução possa ser usada
milhares e milhares de vezes” [ALE77].
7. Padrões de Projeto: Histórico
} Os Designs Patterns originam-se no final dos anos 80,
} quando Ward Cunningham e Kent Beck desenvolveram um
conjunto de padrões para serem aplicados no desenvolvimento de
interfaces do usuário elegantes em Smalltalk.
} No mesmo período, Jim Coplien estava desenvolvendo um catálogo
de padrões C++ chamados idiomas.
8. Padrões de Projeto: Histórico
} Erich Gamma estava trabalhando em sua tese de doutorado sobre
desenvolvimento de software orientado a objeto, e reconheceu a
importância de acumular explicitamente as estruturas de projetos
que se repetiam com frequência.
} Em 1994, quatro autores – Erich Gamma, Richard Helm, Ralph Johnson e John
Vlissides - publicaram o primeiro catálogo de Design Patterns para programas
orientado a objetos: Design Patterns – Elements of Reusable Object-Oriented
software.
} Esse livro descreve soluções simples para problema específicos no
projeto de software orientado a objetos.
9. Padrões de Projeto: Aplicado em Outras Áreas
} No seu livro - A Pattern Language: Towns, Buildings,
Construction - mostra como patterns podem ser
aplicados na construção de casas, assim como no
planejamento de bairros e cidades.
10. Motivação
} Tornar o desenvolvimento de software OO uma tarefa
menos complexa.
} Possibilitar que desenvolvedores iniciantes possam fazer
uso de padrões de projetos catalogados por “experts”.
} Criar uma padronização para soluções de projeto OO.
11. Conceito Básico
} Cada padrão descreve um problema que ocorre inúmeras
vezes.
} É descrito a essência da solução para esse problema.
} Solução pode ser reutilizada sempre que esse problema
vier a aparecer em qualquer projeto de sistema.
12. Conceito Básico (continuação....)
} Descreve uma situação onde várias classes cooperam
para realizar uma determinada tarefa.
} É determinado uma organização específica, ou seja,
micro-arquiteturas de classe e objetos com seus papeis e
colaborações.
} Na descrição de um padrão alguns componentes são
essenciais para o seu entendimento com: nome, problema,
solução e conseqüências.
13. Exemplo Editor de Desenho
Shape
Limite()
CriaManipulador()
EditorDesenho
LinhaShape
Limite()
CriaManipulador()
PoligonoShape
Limite()
CriaManipulador()
TextView
GetExtensao()
Problema
14. Exemplo Editor de Desenho
Shape
Limite()
CriaManipulador()
EditorDesenho
LinhaShape
Limi te()
CriaMani pulad or()
PoligonoShape
Limite()
CriaManipulador()
TextView
GetExtensao()
TextShape
Limite()
CriaManipulador()
Text
return text.getExtent()
return new TextManipulador
Solução
15. Objetivo
l Converter a interface de classe em outra interface
esperada pelo cliente.
l Permite que classes trabalhem juntas mesmo com
interfaces incompatíveis.
16. Motivação
l Fazer uso de reutilização mesmo quando temos
classes com interfaces diferentes das que são
necessárias pela aplicação.
17. Aplicabilidade
l Quando se quer usar uma classe existente, e sua
interface não for igual a que você necessita.
l Quando você não tem o código fonte da classe a ser
adaptada.
l Quando a classe é genérica , e assim, não se deve
altera a classe para uma aplicação específica.
18. Estrutura Genérica
Com Herança múltipla
The image cannot be displayed. Your computer may not have enough memory to open the image, or the image may have been corrupted. Restart your computer, and then open the file again. If the red x still appears, you may have to delete the image and then
insert it again.
20. Participantes
l Objetivo (Shape) – Define o domínio específico que
é usado pelo Cliente.
l Cliente (EditorDesenho) – Colabora com objetos
conforme a interface da classe Objetivo.
l Adaptada (TextView) – Define uma interface
existente que necessita ser adaptada.
l Adaptador (TextShape) – Adapta a interface da
classe Adaptada para interface da classe Objetivo.
21. Colaborações entre objetos
l Clientes(Editor Desenho) chamam operações
de instancias do Adaptador(TextShape).
l Em troca, o Adaptador (TextShape) chama
operações da classe Adaptada (TextView).
l Delegação de funções.
22. Consequências do uso do padrão ADAPTER
l O Cliente (EditorDesenho) e a classe Adaptada
(TextView) permanecem inalteradas.
l Com a chamada de funcionalidade indiretas o
programa se torna mais complexo.
l A Classe Adapter pode determinar que métodos
devem ser chamados de outro objeto.
23. Projeto Exemplo
} O objetivo deste projeto é a construção de um conjunto
de classes que permitam a criação de Editor de Desenho
fictício. O EditorDesenho objetiva imprimir o limite X,Y
de seus possíveis Shapes. O problema aqui estabelecido é
necessidade de adaptar a classe Textview para funcionar
neste editor. O padrão a ser utilizado é o Adapter.
25. Tratamento de Exceções
} Uma exceção e uma condição anormal que surge em uma
sequência de código em tempo de execução.
} Muitas Linguagens usam código de retorno das funções
chamadas para sinalizar erros.
} Procedimento sujeito a problemas.
} Complexidade no encadeamento do código.
} Falta de detalhes sobre o erro.
27. Especificando métodos que lançam
exceções
} Quando não for adequado capturar uma exceção pode-se lança-lá para cima.
O método que fizer chamada a um método que lança uma exceção e obrigado a:
Capturar / Lançar / Capturar e Lançar.
} public void adicionaContato(IF_Contato c) throws Exception{
} If(!this.mConato.containsKey(c.getTelefone()){
} This.mContato.put(c.getTelefone(),c)
} else{
} Exception e = new Exception(“Contato já existe!);
} throw e;
} }}
} public void cadastraContato(String nome, String telefone) throws Exception{
} IF_Contato c = new Contato();
} c.setNome(nome); c.setTelefone(telefone);
} Agenda.getInstancia().adicionaContato(c);
} }
}
28. Especificando métodos que lançam
exceções
}
Quando não for adequado capturar uma exceção pode-se lança-lá para cima.
O método que fizer chamada a um método que lança uma exceção e obrigado a:
Capturar / Lançar / Capturar e Lançar.
}
//Lançar
public InputFileDeclared(String filename) throws FileNotFoundException {
in = new FileInputStream(filename);
}
} //Capturar e Lançar.
public void InputFileDeclared_v1(String filename) throws FileNotFoundException {
try{
in = new FileInputStream(filename);
}catch(FileNotFoundException e){
System.out.println("Erro gerado no método"+ e);
throw e;
}
}
29. Tratamento de Exceções
} Em Java o tratamento de exceções é gerenciado por meio
das palavaras-chave:
try{
// Bloco de Código
}catch (ExcecaoTipo e){
//Bloco de Código
throw(e);
}
32. Finaly
} finaly - Quando for necessário ter certeza que um determinado código
será executado independente das exceções que são cousadas ou
capturadas.
try {
. . .
out.close(); // Não existe a garantia que esse código será
executado se houver algum problema.
} catch (ArrayIndexOutOfBoundsException e) {
out.close(); // Não existe a garantia que esse código será
executado se houver algum problema.
System.err.println("Caught ArrayIndexOutOfBoundsException: " + e.getMessage());
} catch (IOException e) {
System.err.println("Caught IOException: " + e.getMessage());
}
finally {
if (out != null) {
System.out.println("Closing PrintWriter");
out.close();
} else {
System.out.println("PrintWriter not open");
}
}
33. Objetivo
} “Template Method” define o esqueleto de um algoritmo
para uma operação, transferindo alguns passos desta
operação para as subclasses.
} Este padrão permite que uma subclasse redefina certos
passos de um algoritmo, sem alterar a estrutura do
mesmo.
34. Objetivo (fonte Jacques )
} Define o esqueleto de um algoritmo numa operação,
deixando que subclasses completem algumas das etapas.
} O padrão Template Method permite que subclasses
redefinem determinadas etapas de um algoritmo sem
alterar a estrutura do algoritmo.
} Resumo
} Um Template Method define um algoritmo usando operações
abstratas
} Subclasses fazem override das operações para prover um
comportamento concreto
} Este padrão é a base para a construção de frameworks
35. Quando usar o padrão Template
Method? (fonte Jacques )
} Para implementar partes invariantes de um algoritmo uma única vez e
deixar subclasses implementarem o comportamento variável
} Quando comportamento comum entre subclasses deveria ser refatorado e
localizado numa classe comum para evitar duplicação
} É um passo frequente de "refactoring" de código
} Primeiro identifique as diferenças
} Coloque as diferenças em novos métodos
} Substitua o código das diferenças por uma chamada a um dos novos
métodos
} Para controlar extensões de subclasses
} Você pode definir um Template Method que chame operações-gancho
(hook) e pontos específicos, permitindo extensões apenas nestes pontos
} Faça com que apenas os métodos-gancho possam sofrer override
38. Participantes
} TemplateAbstrata (Login)
} Define operações abstratas que subclasses concretas definem
para implementar certas etapas do algoritmo
} Implementa um Template Method (logon()) definindo o
esqueleto de um algoritmo
} O Template Method chama várias operações, entre as quais as
operações abstratas da classe
} TemplateConcreta (LoginAplicação)
} Implementa as operações abstratas para desempenhar as
etapas do algoritmo que tenham comportamento específico a
esta subclasse
40. } Mensagem
} public String envia(Destinatario destinatario)throws Exception{
} this.verifica();
} return "Mensagem para "+destinatario.getNomeCompleto()+"
"+this.getTxtMensagem();
}
} }
41. Email
} public void verifica()throws Exception{
} if (this.getAssunto().isEmpty()){
} throw new Exception("Assunto não está preenchido!");
} }
} }
} public String getTxtMensagem(){
} return "EMAIL;"+super.getDataHora()+";"+super.getEmail()+";"+this.getAssunto()
+";"+super.getConteudo();
} }
42. SMS
} public void verifica()throws Exception{
} if(!(this.conteudo.length()<=20)){
} throw new Exception("Conteúdo maior do que vinte caracteres!");
} }
} }
} public String getTxtMensagem(){
} return "SMS;"+this.getTelefone()+";"+super.getConteudo()+";"+super.getDataHora();
}
} }
43. main
} Destinatario[] d = new Destinatario[2];
}
} d[0]= new Destinatario(); d[0].setNome("emjorge"); d[0].setNomeCompleto("Eduardo M. F. jorge");
}
} d[1]= new Destinatario(); d[1].setNome("camila"); d[1].setNomeCompleto("Camila S. P. Jorge");
}
} Mensagem email = new Email("emjorge@gamil.com","Prova Tópicos II","03/10/2005","Aviso");
} Mensagem email1 = new Email("emjorge@gmail.com","Prova Tópicos II","03/10/2005","");
} Mensagem sms = new Sms("camila@gmail.com","A Prova de Tópicos II será na sala
36","03/10/2005","9129-2234");
} Mensagem sms1 = new Sms("camila@gmail.com","Prova Tópicos II","03/10/2005","9129-2234");
}
}
45. Objetivo
} Possibilitar que objetos registrados em um serviço sejam
notificados da mudança de estado ou de outros eventos
que ocorram no objeto que gerencia o serviço.
} "Definir uma dependência um-para-muitos entre objetos
para que quando um objeto mudar de estado, todos os
seus dependentes sejam notificados e atualizados
automaticamente." [GoF]
46. Quando usar o padrão Observer?
(fonte Jacques )
} Quando uma abstração tem dois aspectos, um
dependente do outro. Encapsular este aspectos em
objetos separados permite que variem e sejam reusados
separadamente.
} Quando uma mudança a um objeto requer mudanças a
outros e você não sabe quantos outros objetos devem
mudar.
} Quando um objeto deve ser capaz de avisar outros sem
fazer suposições sobre quem são os objetos. Em outras
palavras, sem criar um acoplamento forte entre os
objetos.
48. Participantes
} Participantes
} Subject – Classe abstrata que contempla a
funcionalidade de registrar e notificar os Objetos
(Observer)
} Observer – Interface implementada por Objetos a
serem notificados
} ConcreteSubject - possui estados de interesse dos
objetos notificados. Responsável pela notificação dos
Objetos quando o estado muda.
} ConcreteObserver - Implementa a interface Observer.
Armazena o estado que deve estar consistente com base
no ConcreteSubject
49. Conseqüências
} permite reusar Subjects sem reusar seus Observers
e vice-versa;
} suporte para comunicação em broadcast (a notificação é
enviada pelo Subject automaticamente para todos os
Observers subscritos);
} atualizações inesperadas (cuidar dos critérios de
dependência).
} o custo de uma mudança ao estado de um Subject pode
ser grande se houver muitos Observers
Adaptado de Fonte
http://www.deinf.ufma.br/~vidal/Topicos/observer.pdf e Jacques