Padres de Projeto Comportamentais Padres de Projeto Orientados

  • Slides: 99
Download presentation
Padrões de Projeto Comportamentais Padrões de Projeto Orientados a Objetos Profa. Danielle Martin Universidade

Padrões de Projeto Comportamentais Padrões de Projeto Orientados a Objetos Profa. Danielle Martin Universidade de Mogi das Cruzes

Padrão de Projeto Descrição da essência de uma solução comum apropriada a um problema

Padrão de Projeto Descrição da essência de uma solução comum apropriada a um problema conhecido e recorrente. Define boas práticas de programação. Facilita o reuso, flexibilidade e simplicidade do software. Deve ser suficientemente abstrato para ser reutilizado em diferentes aplicações.

23 Padrões de projeto – Gang of Four (Go. F) Padrões de Projeto: Soluções

23 Padrões de projeto – Gang of Four (Go. F) Padrões de Projeto: Soluções reutilizáveis de software orientado a objetos Gang of four: • • Erich Gamma Richard Helm Ralph Johnson John Vlissides Publicado em 1994. Referência no assunto de design patterns.

Classificação dos padrões Go. F Criacionais – De criação: Dizem respeito à criação de

Classificação dos padrões Go. F Criacionais – De criação: Dizem respeito à criação de objetos. Estruturais – De estrutura: Tratam da composição de classes e objetos. Comportamentais – Do comportamento: Tratam da colaboração (interação e responsabilidade) entre classes e objetos.

Classificação dos padrões Go. F Os padrões Go. F classificados por categorias são: Criação

Classificação dos padrões Go. F Os padrões Go. F classificados por categorias são: Criação Estrutura Comportamento Classe Factory Class Adapter Interpreter Template Method Objeto Abstract Factory Builder Prototype Singleton Object Adapter Bridge Composite Decorator Facade Flyweight Proxy Chain of Responsibility Command Iterator Mediator Memento Observer State Strategy Visitor

Classificação dos padrões Go. F Os padrões Go. F classificados por categorias são: Criação

Classificação dos padrões Go. F Os padrões Go. F classificados por categorias são: Criação Estrutura Comportamento Classe Factory Class Adapter Interpreter Template Method Objeto Abstract Factory Builder Prototype Singleton Object Adapter Bridge Composite Decorator Facade Flyweight Proxy Chain of Responsibility Command Iterator Mediator Memento Observer State Strategy Visitor

PADRÃO TEMPLATE METHOD

PADRÃO TEMPLATE METHOD

O problema Existem classes que montam e exportam relatórios para dois tipos de relatórios:

O problema Existem classes que montam e exportam relatórios para dois tipos de relatórios: financeiros e de horas de projeto. O algoritmo para montar relatórios é sempre o mesmo consistindo nas seguintes operações: – montar o cabeçalho – montar o corpo – montar o rodapé

O problema Os detalhes da geração de cada relatório podem variar, por isso a

O problema Os detalhes da geração de cada relatório podem variar, por isso a criação de classes filhas. Porém, relatórios para o mesmo departamento podem manter o cabeçalho e o rodapé e variar o conteúdo do corpo. Em outros cenários pode ser necessário variar também o cabeçalho e o rodapé. A única coisa que continua constante é a estrutura e sequência do algoritmo. É possível fazer o reuso do algoritmo nessas situações?

A solução: padrão template O padrão template method resolve casos em que parte de

A solução: padrão template O padrão template method resolve casos em que parte de um determinado algoritmo depende da implementação de classes filhas, mas a estrutura do algoritmo é única. Características: – 1. Definimos uma classe abstrata com métodos abstratos e métodos concretos – 2. Nos métodos concretos da classe abstrata, definimos a estrutura dos algoritmos, chamando seus métodos abstratos, mesmo sem saber qual será a implementação. – 3. Definimos sub-classes que implementam os métodos abstratos.

A solução: padrão template O método montar. Relatorio é o método template, que define

A solução: padrão template O método montar. Relatorio é o método template, que define quais métodos e em que ordem devem ser chamados para se montar um relatório, ainda que a implementação dos métodos abstrados ainda seja desconhecida.

Classe Relatorio Método template

Classe Relatorio Método template

Outro exemplo Reaproveitando mesmo cabeçalho e rodapé para todos os tipos de relatórios financeiros:

Outro exemplo Reaproveitando mesmo cabeçalho e rodapé para todos os tipos de relatórios financeiros:

Classes Relatorio. Financeiro

Classes Relatorio. Financeiro

Classe aplicação

Classe aplicação

PADRÃO INTERPRETER

PADRÃO INTERPRETER

O problema Precisamos criar uma aplicação que resolva expressões numéricas que são entradas no

O problema Precisamos criar uma aplicação que resolva expressões numéricas que são entradas no formato String. Por exemplo: 1 + 2 * (3 + 4) Como implementar esse algoritmo?

A solução: padrão interpreter Pode-se quebrar a lógica de interpretação de uma expressão matemática

A solução: padrão interpreter Pode-se quebrar a lógica de interpretação de uma expressão matemática em algumas etapas executadas sequencialmente: – Interpretar parêntesis – Interpretar multiplicação e divisão – Interpretar adição e subtração A ideia do padrão interpreter é criar uma estrutura de classes para traduzir expressões com gramática complexa. Cada classe é responsável por interpretar parte ou termo da expressão e no final os resultados são combinados para trazer o resultado traduzido. Outro exemplo de uso: Compiladores

A solução: padrão interpreter Classes interpretadoras:

A solução: padrão interpreter Classes interpretadoras:

Classes interpretadoras

Classes interpretadoras

Classe interpretadora Obs: a primeira classe interpretadora (quem inicia a tradução) pode ser Considerada

Classe interpretadora Obs: a primeira classe interpretadora (quem inicia a tradução) pode ser Considerada uma implementação do padrão facade, pois define as regras de como os demais interpretadores serão acionados.

Aplicação principal

Aplicação principal

Interpretadores adicionais

Interpretadores adicionais

PADRÃO CHAIN OF RESPONSIBILITY

PADRÃO CHAIN OF RESPONSIBILITY

O problema Precisa-se de um algoritmo para contagem de notas em um caixa eletrônico.

O problema Precisa-se de um algoritmo para contagem de notas em um caixa eletrônico. As notas devem ser retornadas na menor quantidade possível, considerando a quantidade de notas disponíveis para cada valor e imprimindo uma mensagem se o total não atender ao valor solicitado.

Solução? Algoritmo Dinheiro enquanto (din>=10) faça Declare cn 10 : = cn 10 +

Solução? Algoritmo Dinheiro enquanto (din>=10) faça Declare cn 10 : = cn 10 + 1; din como inteiro; {din significa o dinheiro que vai ser decomposto} din : = din - 10; cn 100, cn 50, cn 10, cn 5, cn 1 como inteiro; {cn significa o contador de fim enquanto; cedulas} enquanto (din>=5) faça Início cn 5 : = cn 5 + 1; {validando um valor valido para o dinheiro} din : = din - 5; Repita fim enquanto; escreva 'Digite um valor valido'; Leia din; enquanto (din >=1) faça Até (din>0); cn 1 : = cn 1 + 1; escreva 'o valor que será decomposto é: ', din, 'reais'; din : = din - 1; cn 100 : = 0; fim enquanto; cn 50: =0; escreva 'a quantidade de notas de 100 é: ', cn 100, '; de 50 é: ', cn 10 : = 0; cn 50, '; de 10 é: ', cn 10, '; de 5 é: ', cn 5, '; e de 1 é de: ', cn 1; cn 5 : = 0; FIM algoritmo cn 1 : = 0; enquanto (din >= 100) faça cn 100 : = cn 100+1; din : = din - 100; fim enquanto; Problemas: enquanto (din>= 50) faça - Código extenso cn 50 : = cn 50 + 1; din : = din - 50; - E se não houver a quantidade de notas disponível? fim enquanto; - Não existem mais notas de 1! Refazer o algoritmo?

A solução: padrão Chain of Responsibility Cria-se uma cadeia de classes com uma interface

A solução: padrão Chain of Responsibility Cria-se uma cadeia de classes com uma interface comum. Cada objeto dentro da cadeia possui um ponteiro que referencia o objeto da próxima classe. Ex: existe uma classe para cada tipo de Cedula existente no caixa eletrônico – a cadeia de objetos é criada na ordem da cédula de maior valor para a de menor valor. A requisição é entregue ao primeiro objeto da cadeia de receptores potenciais. Em ordem, os objetos da cadeia atendem à requisição e/ou a encaminham para o próximo objeto da fila até que a requisição seja atendida ou a fila acabe.

A solução: padrão Chain of Responsibility

A solução: padrão Chain of Responsibility

Classes cédulas

Classes cédulas

Classe Caixa. Eletronico Cria a cadeia de objetos

Classe Caixa. Eletronico Cria a cadeia de objetos

Classe Aplicacao

Classe Aplicacao

PADRÃO ITERATOR

PADRÃO ITERATOR

O problema Existem várias classes de collections do java com diferentes algoritmos de armazenamento

O problema Existem várias classes de collections do java com diferentes algoritmos de armazenamento e busca. Ex: Array. List, Vector, Hash. Set, Priority. Queue, Linked. List, Stack. É necessário criar uma interface comum a todas elas que permita a iteração por todos os elementos da lista, seja percorrendo uma lista ordenada, uma estrutura de árvore, etc. É possível?

A solução: padrão Iterator O padrão Iterator cria uma interface comum a classes cuja

A solução: padrão Iterator O padrão Iterator cria uma interface comum a classes cuja função é percorrer uma estrutura de dados. Vantagens: – Desacopla a forma de percorrer a estrutura da forma de armazenamento dos dados – Permite percorrer uma estrutura de várias forma diferentes. Ex: percorrer uma árvore bintária em pré-ordem, in-ordem ou pós-ordem

Exemplo Iterator

Exemplo Iterator

Classes Iteradoras

Classes Iteradoras

Classe Aplicação

Classe Aplicação

PADRÃO MEMENTO

PADRÃO MEMENTO

O problema Em uma aplicação que permite a edição de desenhos e documentos de

O problema Em uma aplicação que permite a edição de desenhos e documentos de texto, precisa-se implementar a ação desfazer, que cancela a última modificação feita no sistema e retorna o objeto modificado ao seu estado original antes da modificação. Como implementar um algoritmo que armazene e restaure objetos de classes diferentes com formatos diferentes?

A solução: padrão Memento A classe Memento permite armazenar o estado atual de um

A solução: padrão Memento A classe Memento permite armazenar o estado atual de um objeto, por exemplo em formato String. O padrão memento define objetos que podem criar mementos e ser restaurados a partir de um memento existente.

Classe Memento

Classe Memento

Restauráveis

Restauráveis

Restauráveis

Restauráveis

Classe Restaurador. Historico

Classe Restaurador. Historico

Classe Aplicacao

Classe Aplicacao

PADRÃO STRATEGY

PADRÃO STRATEGY

O problema Imagine um cenário de um sistema para lojas que deve permitir a

O problema Imagine um cenário de um sistema para lojas que deve permitir a execução das as seguintes regras para os pagamentos e descontos para suas vendas. Formas de pagamento – A vista - Aplica-se um desconto proporcional ao valor da venda. • Acima de 300, 00 - 10 % de desconto • Acima de 500, 00 - 15 % de desconto – A prazo - Deve ser acrescido 8% de juros sobre o valor da venda.

Solucao? Problemas: • O método faz uso intensivo de if's e else's para testar

Solucao? Problemas: • O método faz uso intensivo de if's e else's para testar opções de pagamento e tomar o fluxo correto. Sinais de um código pouco coeso. • Para modificar qualquer regra de pagamento, deve-se primeiro encontrar a condicional entre muitas opções, o que pode gerar erros e quebrar o código que já esta funcionando. • Para adicionar uma nova regra de pagamento, deve-se implementar uma nova condicional, o que pode tornar este código cada vez mais complexo.

Solucao: Padrao Strategy Para melhorar o código anterior, podemos isolar o elemento da classe

Solucao: Padrao Strategy Para melhorar o código anterior, podemos isolar o elemento da classe Venda que varia, a regra para o calculo de descontos ou acréscimo de juros, em sua própria hierarquia de classe conforme o diagrama apresentado a seguir:

Solucao: padrao Strategy O padrao Strategy tem como objetivo central o encapsulamento de algoritmos

Solucao: padrao Strategy O padrao Strategy tem como objetivo central o encapsulamento de algoritmos que podem variar com facilidade para prover um comportamento mais adequado para um objeto de acordo com um contexto. Aspectos positivos – – – O algoritmo poder ser alterado sem a modificação da classe Venda. A partir dessa estrutura, novas implementações podem ser criadas e introduzidas posteriormente. A lógica condicional na classe Venda foi reduzida. Como a escolha do algoritmo está na implementação do objeto que está compondo a classe, isso elimina a necessidade de ter condicionais para selecionar a lógica a ser executada. A implementação pode ser trocada em tempo de execução, assim o comportamento da classe é alterado dinamicamente, uma aplicação de polimorfismo. Aspectos negativos – – O aumento da complexidade na criação do objeto, pois a instância da dependência precisa ser criada e configurada. Caso o atributo seja nulo, a classe pode apresentar um comportamento inesperado. O aumento do número de classes. Há uma para cada algoritmo, podendo criar uma maior dificuldade em seu gerenciamento

Classes Regras de Pagamento

Classes Regras de Pagamento

Classe Venda

Classe Venda

Classe Aplicacao

Classe Aplicacao

PADRÃO STATE

PADRÃO STATE

O problema Um objeto pode passar por vários estados ao longo de seu ciclo

O problema Um objeto pode passar por vários estados ao longo de seu ciclo de vida. O diagrama de estados da UML nos ajuda a identificar e representar esses estados e suas transições. O seguinte diagrama, por exemplo, representa os estados da matrícula de um aluno em uma disciplina. Como implementar esse controle dos estados da matrícula em nossas classes?

Solução 1? – atributos booleanos? Apesar de parecer uma abordagem simples, usar vários atributos

Solução 1? – atributos booleanos? Apesar de parecer uma abordagem simples, usar vários atributos para gerenciar um estado dificulta o controle sobre o objeto: nada impede que em determinado momento, dois desses estados sejam setados para true ao mesmo tempo.

Solução 2? – atributo String Utilizar um único atributo para armazenar o estado é

Solução 2? – atributo String Utilizar um único atributo para armazenar o estado é uma maneira melhor de centralizar o controle. Porém, como impedir que existam objetos com status = “Cursando” e outros com status = “cursando" ou outras divergências na escrita da String que possam prejudicar o funcionamento correto do sistema? Ou ainda impedir que o objeto receba um estado que não foi planejado na aplicação?

Solução 3? – atributo int? Usar o atributo status do tipo int evita que

Solução 3? – atributo int? Usar o atributo status do tipo int evita que um mesmo status possa ser escrito de formas diferentes. Mas como controlar qual número é associado a qual status? Seria necessário acrescentar um dicionário nos comentários do código e fazer a tradução toda vez que o status for exibido na aplicação. E como impedir que outros números sejam setados no status?

Solução 4 - Enum O enum é um tipo especial de dados que consiste

Solução 4 - Enum O enum é um tipo especial de dados que consiste num set de constantes pré definidas. Dessa forma, ao definir o tipo do atributo status como Situacao, garante-se que somente as constantes pré definidas do enum sejam valores válidos para esse atributo.

Solução 4 - Enum Vantagens: 1. Impossível setar o status para um valor que

Solução 4 - Enum Vantagens: 1. Impossível setar o status para um valor que não esteja no enum 2. Usando o nome da constante, é impossível haver erros de digitação, pois o programa não compilaria 3. Novas constantes podem ser criadas no enum sem a necessidade de refatorar a classe Matricula.

Código Java com Enum

Código Java com Enum

Código Java com Enum

Código Java com Enum

O problema, parte 2 A utilização de enums é fortemente recomendada para monitorar status

O problema, parte 2 A utilização de enums é fortemente recomendada para monitorar status de objetos simples, definir tipos de objetos, ou até perfis de acesso de usuários. No entanto, algumas situações requerem um controle ainda mais forte sobre os estados de seus objetos, que é o caso onde cada estado desencadeia um comportamento diferente no objeto. Por exemplo, o que aconteceria se o programador tentasse trancar uma matrícula que já estivesse concluída? Ou aprovar um aluno cuja matrícula nunca foi confirmada? Para esses casos, existe uma alternativa que pode ser implementada, o padrão State.

Solução 5 – Padrão State Com o padrão State, cada estado do objeto será

Solução 5 – Padrão State Com o padrão State, cada estado do objeto será manipulado por uma classe diferente, todas implementam a mesma interface e sobrescrevem os mesmos comportamentos - estes que variam de acordo com o estado atual do objeto.

Solução 5 – Padrão State A classe Matricula, por sua vez, delega a execução

Solução 5 – Padrão State A classe Matricula, por sua vez, delega a execução de cada comportamento variável para o objeto status. Por exemplo, o método aprovar, no lugar de um código extenso repleto de “ifs”, teria apenas uma chamada para this. status. aprovar(); Dependendo do status atual do objeto, uma das sobrescritas da interface Situação seria acionada polimórficamente. Vantagens: 1) Maior controle sobre como cada estado se comporta em cada ação 2) Impossível esquecer de codificar um estado respondendo a um método, pois cada subclasse deve implementar todos os métodos da interface 3) É possível lançar a exceção Illegal. State. Exception caso uma operação que não é permitida em determinado estado seja acionada

Codigo Java com State

Codigo Java com State

Codigo Java com State

Codigo Java com State

Codigo Java com State Os blocos de try/catch foram adicionados ao código acima apenas

Codigo Java com State Os blocos de try/catch foram adicionados ao código acima apenas para efeito de teste. Na aplicacao real, uma troca ilegal de estado deveria parar a execucao e notificar o usuario.

PADRÃO COMMAND

PADRÃO COMMAND

O problema Frequentemente, ao desenvolver aplicações web usando Servlets, nos deparamos com uma servlet

O problema Frequentemente, ao desenvolver aplicações web usando Servlets, nos deparamos com uma servlet de controle assim:

O problema Esta resolução é considerada um Anti-Pattern, pois no lugar de modelarmos uma

O problema Esta resolução é considerada um Anti-Pattern, pois no lugar de modelarmos uma classe por comando temos todas as lógicas agrupadas em uma só classe. O acréscimo de funcionalidades, tais como: Consultar e Excluir, implicará na construção de vários outro IF-else, tornando a modelagem menos flexível em termos de reuso / extensão e manutenção de código.

A solucao: padrao Command O padrao Command recomenda o uso de um objeto para

A solucao: padrao Command O padrao Command recomenda o uso de um objeto para representar uma solicitação, permitindo o encapsulamento de sua implementacao física. Cada ação da controle seria encapsulada em uma classe distinta. Cada classe implementa uma interface comum, a Command.

Command + Factory Para desacoplar ainda mais o cliente que requisita a solicitacao da

Command + Factory Para desacoplar ainda mais o cliente que requisita a solicitacao da classe que a implementa, pode-se usar o padrao Factory em conjunto com o Command. Dessa forma, apenas uma Servlet é necessária em toda a aplicação e ela assume a responsabilidade de redirecionar as solicitações às classes corretas.

Classes Command

Classes Command

Classe Controller. Factory

Classe Controller. Factory

Executando o commando Ao acionar um comando com uma requisição HTTP, seja GET ou

Executando o commando Ao acionar um comando com uma requisição HTTP, seja GET ou POST, a nossa Controller. Factory irá localizar a classe apropriada e redirecionar o resultado para a página indicada pela classe de commando.

PADRÃO VISITOR

PADRÃO VISITOR

O problema Uma fábrica de produção armazena três tipos de dados de produtos de

O problema Uma fábrica de produção armazena três tipos de dados de produtos de acordo com o estágio de produção em que se encontram: – Produto matéria prima, – Produto em produção, e – Produto em estoque. Existem dois tipos de relatórios que podem ser gerados para cada tipo de produto: – Relatório em PDF, e – Relatório em XLS.

O problema Como podemos relacionar cada tipo de produto com os diferentes tipos de

O problema Como podemos relacionar cada tipo de produto com os diferentes tipos de relatórios de forma dinâmica e sem dependências (um produto não deve ter um tipo de relatório fixo)?

A solução: padrão Visitor O padrão Visitor permite que um objeto de uma hierarquia

A solução: padrão Visitor O padrão Visitor permite que um objeto de uma hierarquia visite um objeto de outra hierarquia para realizar uma tarefa sobre o mesmo.

A solução: padrão Visitor O termo “visitar” se dá pois o acoplamento entre os

A solução: padrão Visitor O termo “visitar” se dá pois o acoplamento entre os objetos é mínimo: ao contrário do padrão Bridge, no Visitor não há composição e nem dependência, apenas uma associação temporária entre ambos. Pode-se combinar o padrão Visitor com o Factory ou Singleton, para gerenciar a vida das classes de relatorio. Pode-se usar o Visitor para facilitar a comunicação entre classes que implementam estrturas de dados, como a Composite ou Interpreter.

Classes Relatorio

Classes Relatorio

Classes Produto

Classes Produto

Classe aplicação

Classe aplicação

PADRÃO OBSERVER

PADRÃO OBSERVER

O problema Uma ferramenta de compras online permite que o usuário solicite ser notificado

O problema Uma ferramenta de compras online permite que o usuário solicite ser notificado quando surgir uma oferta para um produto de seu interesse. Podemos criar uma classe Interessado para armazenar os clientes interessados, mas como eles serão notificados no momento da alteração do produto? ?

A solução: padrão Observer O padrão Observer permite que objetos observem um objeto de

A solução: padrão Observer O padrão Observer permite que objetos observem um objeto de interesse, aguardando por mudanças em seu estado. Quando houver uma mudança de estado no objeto Observado, todos os Obsevadores serão notificados. A Oferta é o objeto observado e os Interessados são os observadores.

Observer no Java A biblioteca do Java possui uma implementação padrão do Observer, fornecendo

Observer no Java A biblioteca do Java possui uma implementação padrão do Observer, fornecendo a classe Observable e a interface Observer. O padrão Observer também é implementado no Java Swing com os Action. Listeners, que identificam quando um botão ou elemento é acionado na interface gráfica e disparam a ação apropriada.

Classe Observadora

Classe Observadora

Classe Observada

Classe Observada

Classes principais

Classes principais

Aplicação

Aplicação

PADRÃO MEDIATOR

PADRÃO MEDIATOR

O problema Um sistema de tradução automática de texto permite a tradução de mensagens

O problema Um sistema de tradução automática de texto permite a tradução de mensagens entre vários idiomas diferentes. Quanto mais idiomas a ferramenta disponibilizar, maior a quantidade de combinações possíveis de traduções. Como implementar todas essas trocas de mensagens de forma fácil?

A solução: padrão mediator Implementa-se uma classe mediator, que funciona como um mediador de

A solução: padrão mediator Implementa-se uma classe mediator, que funciona como um mediador de relacionamentos muitos para muitos. Assim, permitese fazer a tradução de qualquer idioma para qualquer idioma suportado, sem que estes se conheçam diretamente.

Classes idiomas

Classes idiomas

Classe Mediator

Classe Mediator

Classe principal

Classe principal

Classe principal

Classe principal