Padrões de Projeto
Alcides Calsavara
http://www.ppgia.pucpr.br/~alcides
Referências Bibliográficas
Design Patterns: Elements of Reusable
Object-Oriented Software. Erich Gamma e
outros (GoF), Addison-Wesley, 1995.
Patterns in Java: a catalog of reusable design
patterns illustraded in UML, Volume 1. Mark
Grand, John Wiley & Sons, 1998.
Projeto de Software: da programação à
arquitetura (Software design: from
programming to architecture). Eric Braude,
John Wiley & Sons, 2004.
Design Pattern
(Padrão de Projeto)
Descrição de um problema recorrente,
de forma genérica.
Descrição de uma solução também
genérica, que deve ser adaptada de
acordo com o contexto em que o
problema se manifesta.
Objetivos de projeto
Reusabilidade, flexibilidade e manutenibilidade



reutilize projetos flexíveis
mantenha o código em um nível geral
minimize dependência de outras classes
Robustez


reutilize projetos seguros
reutilize partes robustas
Suficiência e correção


modularize o projeto
reutilize partes confiáveis
Vantagens no uso de DP
Evita a redescoberta de soluções
Propicia o uso de soluções corretas
Melhora a qualidade do software
Melhora a confiabilidade do software
Provê uma linguagem comum entre
desenvolvedores
Reduz o volume de documentação
Economiza esforço e tempo de
desenvolvimento e manutenção
Conduz ao bom uso de orientação a objetos
Exemplo de Problema
Recorrente : Composição
Em um sistema de arquivos, existem arquivos
e pastas (diretórios), sendo que todo arquivo
está contido em uma pasta e toda pasta pode
conter arquivos e também outras pastas.
Em um documento, existem caracteres e
imagens como elementos básicos, e
páginas, colunas, frames e linhas de texto
como elementos compostos, sendo que
todo elemento básico está contido em um
elemento composto e todo elemento
composto pode conter elementos básicos e
também outros elementos compostos.
Composição em
Sistema de Arquivos
ComponenteSistemaArquivos
tamanho
listar ( ) {abstract}
Arquivo
tipo
listar ( )
Pasta
listar ( )
0..*
Composição em
Documento
ElementoDocumento
Caráter
Imagem
Documento
Página
0..*
ElementoCompostoDocumento
Coluna
Frame
LinhaTexto
Composição:
Solução Genérica 1 (GoF)
Component
Client
Operation()
Add(Component)
Remove(Component)
GetChild(int)
0..*
Leaf
Composite
Operation()
Operation()
Add(Component)
Remove(Component)
GetChild(int)
Composição:
Solução Genérica 2 (M. Grand)
AbstractComponent
0..*
operation()
ConcreteComponent1
ConcreteComponent2
AbstractComposite
operation()
operation()
operation()
add(AbstractComponent)
remove(AbstractComponent)
getChild(int)
...
ConcreteComposite1
ConcreteComposite2
operation()
add(AbstractComponent)
remove(AbstractComponent)
getChild(int)
operation()
add(AbstractComponent)
remove(AbstractComponent)
getChild(int)
...
Categorias de padrões (GoF)
CRIACIONAIS: criar uma coleção de
objetos de maneira flexível ou restrita.
ESTRUTURAIS: representar uma
coleção de objetos relacionados.
COMPORTAMENTAIS: captar
comportamento em uma coleção de
objetos.
Padrões de projeto criacionais
Fábrica
Fábrica Abstrata
Protótipo
Objeto Unitário
Padrões de projeto estruturais
Composto
Decorador
Adaptador
Fachada
Padrões de projeto
comportamentais
Comando
Iterador
Interpretador
Observador
Gabarito
Documentação de um DP
(Mark Grand)
Nome
Sinopse
Contexto
Forças
Solução
Conseqüências
Implementação
Uso na API de Java
Exemplo de código
Padrões relacionados
Características de padrões de
projeto
Pontos de vista:


Estático: modelo de classes (do que são
feitos)
Dinâmico: diagrama de seqüência ou de
estados (como funcionam)
Níveis:


Abstrato: descreve o núcleo do padrão
Concreto: descreve as particularidades de
um caso
Padrões Fundamentais
Delegation (Delegação)
Interface (Interface)
Marker Interface (Interface de
Marcação)
Immutable (Imutável)
Proxy
Padrão Delegation (Delegação)
Permite estender e reusar a
funcionalidade de uma classe através
da escrita de classes adicionais com
funcionalidades a mais que usam
instâncias da classe original, a fim de
prover a funcionalidade original.
Padrão Delegation – Exemplo
usando herança
Padrão Delegation – Exemplo
usando herança múltipla
Padrão Delegation – Exemplo
usando delegação
Padrão Interface
Mantém uma classe que usa dados e
serviços providos por instâncias de
outras classes independente dessas
através do acesso a tais instâncias
obrigatoriamente através de uma
interface.
Padrão Interface – Exemplo
sem usar interface
Padrão Interface – Exemplo
usando interface
Padrão Interface – Exercício
Inclua um terceiro tipo de impressora
(ImpressoraCanon) no diagrama de
impressoras e sistema.
Padrão Marker Interface
(Interface de Marcação)
Usa interfaces que não declaram
qualquer método ou variável (atributo)
para indicar propriedades semânticas de
uma classe. Funciona muito bem para
classes utilitárias que precisam
determinar alguma coisa sobre objetos,
sem entretanto precisar assumir que
esses sejam instâncias de alguma classe
em particular.
Padrão Marker Interface –
Exemplo sem usar
Padrão Marker Interface –
Exemplo usando
Padrão Marker Interface –
Exercício
Inclua a interface de marcação
Comprimível para a hierarquia de
classes de documentos.
Padrões de projeto criacionais
Fábrica
Fábrica Abstrata
Protótipo
Objeto Unitário
Padrão Factory Method (Fábrica)
Permite que uma classe genérica (escrita para ser
reusada) instancie outras classes sem que seja
dependente de tais classes, isto é, sem que faça
menção explícita a essas. A classe genérica se
mantém independente das classes que instancia
através da delegação para um outro objeto da
escolha de qual classe instanciar e somente refere-se
ao objeto então criado através de uma interface
comum.
Permite criar objetos desejados utilizando métodos
que retornam os objetos.
Padrão Factory Method – Geral
Padrão Factory Method –
Exemplo
Padrão Abstract Factory
(Fábrica Abstrata)
Kit ou Toolkit
Permite a criação de instâncias de um
conjunto de classes abstratas relacionadas a
partir de respectivo um conjunto de classes
concretas. Pode ser muito útil quando se
precisa trabalhar com uma variedade de
entidades externas complexas.
Permite criar famílias coordenadas de objetos
em tempo de execução, escolhidos a partir de
um conjunto de estilos.
Padrão Abstract Factory - Geral
Padrão Abstract Factory Exemplo
Padrão Prototype (Protótipo)
Permite criar os objetos de um tipo clonando
um protótipo.
Permite um objeto criar objetos customizados
sem saber suas classes exatas e sem saber
detalhes sobre como fazer tal criação.
Funciona através do fornecimento de objetos
protótipos para um objeto que então solicita
de tais protótipos a criação de cópias deles
próprios.
Padrão Protótipo: Geral
Padrão Protótipo: Exemplo
Padrão Singleton
(Objeto Unitário)
Assegura que uma classe tenha exatamente
uma instanciação, acessível por toda
aplicação.
Garante que apenas uma e somente uma
instância de uma certa classe é criada.
Todos os objetos que usam uma instância da
classe usam a mesma instância.
Padrão Singleton - Geral
Padrão Composite (Composição)
Recursive Composition Pattern
Permite representar uma árvore de objetos
tal que o acesso seja uniforme.
Permite construir objetos complexos através
de uma composição recursiva que define uma
árvore de objetos. Todos os objetos são
acessados de maneira consistente e
homogênea, pois todos possuem uma
superclasse ou uma interface comum.
Padrão Composite (Composição)
Há um objeto complexo que deve ser
decomposto numa hierarquia “parte-todo” de
objetos.
Deseja-se minimizar a complexidade numa
hierarquia parte-todo de objetos através da
minimização do número de tipos diferentes
de filhos que precisam ser explicitamente
conhecidos dos objetos da árvore.
Façade (Fachada )
Fornece uma interface para um pacote de
classes.
Regula a comunicaçãoa com os objetos de
um pacote (componente).
Clientes interagem com uma única classe de
um pacote.
A estrutura Fachada está na forma de
delegação.
Permite gerenciar arquiteturas de software
envolvendo grandes números de classes.
Fachada: Geral
Fachada: Exemplo
Padrão Iterator (Iterador)
Define uma interface que declara
métodos para o acesso seqüencial aos
objetos de uma coleção.
Uma classe (cliente) que acessa a
coleção somente através de uma
interface desse tipo permanece
independente da classe que implementa
a interface.
Padrão Iterador: Geral
Padrão Iterador: Exemplo
Padrão Command (Comando)
Encapsula comandos em objetos tal que
é possível controlar sua seleção e
seqüenciamento, enfileirá-los, desfazêlos (undo ), isto é, manipulá-los de
forma geral.
Permite tornar a execução de operações
mais flexível (ex: desfazer).
Padrão Comando – Geral
Padrão Comando - Exemplo
Padrão Observer (Observador)
Permite que objetos registrem dinamicamente
suas dependências de outros objetos.
Um objeto especial notificará os objetos
dependentes sempre que os objetos dos
quais dependem sofrerem alteração de
estado.
Permite atualizar um conjunto de objetos
quando um certo objeto sofrer modificação.
Padrão Observador - Geral
Padrão Observador - Exemplo
Padrão Adapter (Adaptador)
Permite que uma aplicação utilize
funcionalidades externas.
Uma classe Adapter implementa uma
interface conhecida dos clientes e permite
acesso a instâncias de uma classe não
conhecida dos clientes.
Um objeto Adapter provê a funcionalidade
prometida por uma interface sem fixar a
classe que de fato implementa a interface.
Padrão Adapter - Geral
Padrão Adapter – Exemplo 1
Padrão Adapter – Exemplo 2
Decorator (Decorador)
Permite adicionar e remover
responsabilidades de uma classe em
tempo de execução (dinamicamente).
Alternativa flexível a
generalização/especialização para
extensão de funcionalidade.
Decorator - Geral
Decorator – Exemplo 1
Decorator – Exemplo 2
Padrão Strategy (Estratégia)
Encapsula algoritmos relacionados em
classes que são subclasses de uma
classe comum.
Permite a seleção de algoritmo variar
por objeto e também no decorrer do
tempo.
Padrão Strategy – General
Padrão Strategy – Exemplo 1
Padrão Strategy – Exemplo 2
Interpreter (Interpretador)
Permite analisar sintaticamente uma
expressão.
Interpreter - Geral
Interpreter - Exemplo
Padrão Guarded Suspension
Suspende a execução de uma chamada
de método até que uma pré-condição
seja satisfeita.
Exemplo: Guarded Suspension
class Conta {
private double saldo;
public synchronized void saque(double v)
{
while ( saldo < v )
{
try { wait( ); } catch ( InterruptedException e ) { }
}
saldo = saldo – v;
}
public synchronized void deposito(double v)
{
saldo = saldo + v;
notifyAll( );
}
}
Padrão Producer-Consumer
Coordena a produção e o consumo
assíncronos de objetos de informação.
Exemplo: Producer-Consumer
class Queue
{
private Vector data = new Vector( ); // fila de objetos
synchronized public void put( Object obj )
{
data.add( obj ); // insere o objeto na fila
notify( );
}
synchronized public Object get( )
{
while ( data.size( ) == 0 ) // enquanto fila vazia
{
try { wait( ); } catch ( InterruptedException e ) { }
}
Object obj = data.elementAt( 0 ); // primeiro da fila
data.removeElementAt( 0 );
return obj;
}
}
Download

Conceituação