intro padroesprojetoadaptertemplateobserver

51
Design Patternspadrões de projeto para software Orientados a Objeto Eduardo M. F. Jorge ([email protected])

Upload: eduardo-jorge

Post on 15-Jul-2015

71 views

Category:

Education


0 download

TRANSCRIPT

“Design Patterns” padrões de projeto para software Orientados a Objeto

Eduardo M. F. Jorge ([email protected])

Como tornar projetos mais reutilizáveis, com menos acoplamento e com um maior nível de reutilização?

Tarefa para desenvolvedores experientes

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

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.

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].

Singleton

Façade

Abstract Factory

Melhor Leitura do Projeto

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.

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.

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. 

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.

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.

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.

Exemplo Editor de Desenho

Shape

Limite()CriaManipulador()

EditorDesenho

LinhaShape

Lim ite()CriaManipulador()

PoligonoShape

Limite()CriaManipulador()

TextView

GetExtensao()

Problema

Exemplo Editor de Desenho

Shape

Limite()CriaManipulador()

EditorDesenho

LinhaShape

Li mi te()CriaMani pulad or()

PoligonoShape

Limite()CriaM anipulador()

TextView

GetExtensao()

TextShape

Limite()CriaManipulador()

Text

return text.getExtent()

return new TextManipulador

Solução

Objetivo

l  Converter a interface de classe em outra interface esperada pelo cliente.

l  Permite que classes trabalhem juntas mesmo com interfaces incompatíveis.

Motivação

l  Fazer uso de reutilização mesmo quando temos classes com interfaces diferentes das que são necessárias pela aplicação.

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.

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.

Estrutura Genérica

Com Composição (JAVA)

Cliente (EditorDesenho)

Objetivo (Shape)

Pedido()

Adaptada ->PedidoEspecifico()

Adaptador (TextShape)

Pedido()

Adaptada (TextView)

PedidoEspecifico()

Adaptada

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.

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.

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.

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.

Diagrama de Classe

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.

Tratamento de Exceções }  Hierarquia de Classes

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); }  } } 

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; } } 

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); }

Fluxo Exceção

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"); }  } 

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.

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

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

Estrutura Genérica

TemplateAbstrato

templateMethod()#operacao1()#operacao2()

TemplateConc reto

#operacao1()#operacao2()

Exemplo Prático

Logi nlogon()autentica(usuarioID : String, senha : String) : Objectnotif icaAutenticacao(objAutenticacao : Object)

LoginAplicacaoautentica(usuarioID : String, senha : String) : Objectnotif icaAutenticacao(objAutenticacao : Object)

- Obtém Dadosif (autentica(...)) notificaAutenticacao(..)

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

Problema

Método Gabarito

}  Mensagem }  public String envia(Destinatario destinatario)throws Exception{

}  this.verifica();

}  return "Mensagem para "+destinatario.getNomeCompleto()+" "+this.getTxtMensagem();

} 

}  }

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();

}  }

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();

} 

}  }

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("[email protected]","Prova Tópicos II","03/10/2005","Aviso");

}  Mensagem email1 = new Email("[email protected]","Prova Tópicos II","03/10/2005","");

}  Mensagem sms = new Sms("[email protected]","A Prova de Tópicos II será na sala 36","03/10/2005","9129-2234");

}  Mensagem sms1 = new Sms("[email protected]","Prova Tópicos II","03/10/2005","9129-2234");

} 

} 

main }  try{

}  System.out.println(email.envia(d[0]));

}  }catch(Exception e){ System.out.println(e.getMessage()); }

}  try{

}  System.out.println(email1.envia(d[1]));

}  }catch(Exception e){ System.out.println(e.getMessage()); }

}  try{

}  System.out.println(sms.envia(d[0]));

}  }catch(Exception e){ System.out.println(e.getMessage()); }

}  try{

}  System.out.println(sms1.envia(d[1]));

}  }catch(Exception e){ System.out.println(e.getMessage()); }

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]

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.

Estrutura Genérica

Fonte http://www.deinf.ufma.br/~vidal/Topicos/observer.pdf

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

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

Problema

Solução Observer