Professional Documents
Culture Documents
Conteúdo Programático
• PADRÕES CRIAÇÃO • PADRÕES
– Abstract Factory COMPORTAMENTAIS
– Builder – Chain of
– Factory Method Responsibility
– Prototype – Command
– Singleton. – Interpreter
• PADRÕES – Iterator
ESTRUTURAIS – Mediator
– Adapter – Memento
– Bridge – Observer
– Composite – State
– Decorator – Strategy
– Façade – Template Method
– Flyweight – Visitor
– Proxy
Unidade 2 – Padrões GoF
Padrões de Projetos de Software
• Objetivo / Intenção
Padrões de Criação
• Os padrões de criação tem como intenção
principal abstrair o processo de criação de
objetos, ou seja, a sua instanciação.
Padrões de Criação
• Quando se diz que o sistema não precisa se
preocupar com a instanciação do objeto quer
dizer que, se ocorrer alguma mudança neste
ponto, o sistema em geral não será afetado.
Padrões de Criação
• Padrões de criação com escopo de classe vão
utilizar herança para garantir que a flexibilidade.
Por exemplo, o padrão Factory Method pode
criar várias subclasses para criar o produto.
Padrões de Criação
• Abstract Factory
• Builder
• Factory Method
• Prototype
• Singleton.
Abstract Factory
• Intenção:
– Prover uma interface para criação de famílias
de objetos relacionados sem especificar sua
classe concreta.
Abstract Factory
• Motivação:
– Considere uma aplicação com interface gráfica que é
implementada para plataformas diferentes (Motif para UNIX e
outros ambientes para Windows e MacOS).
Abstract Factory
• Motivação (Cont.):
– Podemos solucionar este problema definindo uma classe abstrata
para cada elemento gráfico e utilizando diferentes
implementações para cada aparência ou para cada ambiente.
Abstract Factory
Factory Method
• Intenção:
– Definir uma interface (ou classe abstrata) para a criar
um objeto;
Factory Method
• Motivação:
– Os frameworks usam classes abstratas para
definir e manter relacionamentos entre objetos;
• Considere um framework para
aplicações que podem apresentar
múltiplos documentos pra usuários;
• Duas abstrações chaves:
– Application (aplicação) e Document (documento);
Factory Method
• Problema:
– A classe Application não pode prever a subclasse de
Document a ser instanciada;
Factory Method
• Solução:
– Usar o Factory Method que encapsula o conhecimento sobre a
subclasse de Document que deve ser criado movendo este
conhecimento para fora do framework;
Factory Method
Factory Method
Factory Method
Factory Method
Factory Method
Factory Method
void novoDocumento() {
this.doc = this.criaDocumento();
}
void abrirDocumento() {
this.doc.abrir();
}
}
/**
* Uma implementação do Factory Method. Este método é
* especializado na criação de documentos do tipo
* MeuDocumento
*/
@Override
Documento criaDocumento() {
return new MeuDocumento();
}
}
Singleton
Singleton
• Intenção:
– Garantir que uma classe tenha somente uma
instância e fornecer um ponto global de acesso
para a mesma;
Singleton
• Motivação:
– Em muitas aplicações necessitamos garantir a
ocorrência de apenas uma instância de classes, pois
tais objetos podem fazer uso de recursos cuja
utilização deve ser exclusiva, ou porque se deseja que
os demais elementos do sistema compartilhem um
único objeto particular.
Singleton
• Problema:
– Como garantir que uma classe tenha somente
um instância e que essa instância seja
facilmente acessível?
– Uma variável global torna um objeto acessível,
mas não impede você de instanciar múltiplos
objetos;
Singleton
• Solução:
– Tornar a própria classe responsável por
manter o controle da sua única instancia;
– Padrão Singleton;
Unidade 2 – Padrões GoF
Padrões de Projetos de Software
Singleton – Aplicabilidade
Singleton – Estrutura
Singleton – Estrutura
Singleton
Singleton – Consequências
• Vantagens:
– Acesso controlado à instância única;
– O Singleton tem controle sobre como e quando
clientes acessam a instância;
– Espaço de nomes reduzido;
• O Singleton é melhor que variáveis globais, já que
as “globais” podem ser encapsuladas na instância
única, deixando um único nome externo visível;
Singleton – Consequências
• Vantagens:
– Permite refinamento de operações e de
representação;
• Várias classes Singleton (relacionadas ou não via
herança) podem obedecer a mesma interface,
permitindo que um Singleton particular seja
escolhido para trabalhar com uma determinada
aplicação em tempo de execução;
– Mais flexível que métodos estáticos;
Builder
Builder
• Intenção:
– Propõe que o processo de construção de um objeto, quando
complexo, seja separado da definição do objeto, para que
possamos ter diferentes algoritmos de construção permitindo
diferentes representações para o objeto.
Builder – Estrutura
Builder – Antipattern
• O que é?
– É um padrão de projeto de software que pode ser
comumente usado mas é ineficiente e/ou contra-
produtivo em prática
Builder – Antipattern
• Imaginemos uma situação onde precisamos construir
diferentes tipos de computadores com diferentes
componentes: servidor, computador para games e
computador básico.
Builder – Aplicação
class builder2
ComputadorBuilder
ComputadorDirector
# computador: Computador
~builder
~ builder: ComputadorBuilder
+ createComputador() : void
+ ComputadorDirector(ComputadorBuilder) + addPlacaMae() : void
+ buildComputador() : Computador + addHardDisks() : void
+ getComputador() : Computador
Builder – Exemplo
• Conversor de Texto:
Builder – Exemplo
• Conversor de Texto:
– Neste exemplo, o método lerRTF() (classe LeitorRTF) percorre uma lista
com os tokens encontrados no texto de entrada (formato RTF) e, para
cada tipo de token, chama um método do objeto de tipoConversorTexto.
– Dependendo do formato escolhido para o texto de destino, será escolhida
uma implementação da
classe ConversorTexto: ConversorPDF, ConversorTeX ou ConversorASC
II.
– Cada uma destas classes implementa os métodos de acordo com as
características do formato relacionado.
– A classe ConversorASCII não implementa os
métodos converteParagrafo() e converteFonte() pois este formato (ASCII)
não possui elementos de estilo.
Builder – Código
• ConversorTexto.java
abstract class ConversorTexto {
void converterCaractere(char c) {}
void converterParagrafo() {}
void converterFonte(Fonte f) {}
}
Builder – Código
• ConversorPDF.java
class ConversorPDF extends ConversorTexto {
void converterCaractere(char c) {
System.out.println("Caractere PDF");
}
void converterParagrafo() {
System.out.println("Paragrafo PDF");
}
void converterFonte(Fonte f) {
System.out.println("Fonte PDF");
}
}
Builder – Código
• ConversorTeX.java
class ConversorTeX extends ConversorTexto {
void converterCaractere(char c) {
System.out.println("Caractere TeX");
}
void converterParagrafo() {
System.out.println("Paragrafo TeX");
}
void converterFonte(Fonte f) {
System.out.println("Fonte TeX");
}
}
Builder – Código
• ConversorASCII.java
class ConversorASCII extends ConversorTexto {
void converterCaractere(char c) {
System.out.println("Caractere ASCII");
}
}
Builder – Código
• LeitorRTF.java
class LeitorRTF {
private ConversorTexto conversor;
LeitorRTF(ConversorTexto c) {
this.conversor = c;
}
Builder – Código
• Cliente.java
public class Cliente {
public static void main(String[] args) {
ConversorTexto conversor;
if (args[0].equals("pdf")) {
conversor = new ConversorPDF();
} else if (args[0].equals("tex")) {
conversor = new ConversorTeX();
} else {
conversor = new ConversorASCII();
}
LeitorRTF leitor = new LeitorRTF(conversor);
leitor.lerRTF();
}
}
Prototype
• Apresentação:
– Especifica os tipos de objetos a criar usando
uma instância de protótipo, criando-os
mediante cópia (ou clonagem) deste protótipo.
Prototype
• Aplicabilidade:
– Em situações nas quais deve-se criar
instâncias de objetos a partir de hierarquias de
classes complexas e quando a classe de um
objeto é conhecida somente em tempo de
execução são exemplos do uso deste padrão
de projeto.
Prototype
• Estrutura:
Prototype
• Estrutura:
– Prototype: Uma classe que declara uma interface
para objetos capazes de clonar a si mesmo.
– PrototypeConcreto(1,2,...): Implementação de um
prototype;
Prototype
• Descrição:
– A utilização deste padrão de projeto dá-se pela
existência de uma classe base (ou interface)
contendo a declaração do método clone() e,
dependendo da implementação, mantém um
coleção (na forma de um dicionário, por
exemplo) de classes concretas derivadas da
classe base (ou que implementem a interface).
Prototype
• Exemplo na API Java:
– Este padrão de projeto é a essência da
especificação JavaBean. A interface
java.lang.Cloneable existe para que
classes a implementem, e, assim, atestem que
podem ser clonadas, mediante a sobre-escrita
do método clone(), disponível na classe
java.lang.Object.
Prototype
• Observações:
– Eventualmente, padrões de projeto de criação
competem entre si em uso.
– Às vezes pode-se utilizar ou o padrão de
projeto Prototype ou Abstract Factory.
– Enquanto em outros casos, ambos são
complementos um do outro.
Prototype
• Padrões Relacionados
– Abstract Factory, Composite e Decorator.
Prototype
• Anti-Pattern
– O uso deste padrão de projeto destina-se a criar
cópias (clones) a partir de uma instância denominada
protótipo.
– Assim, o seu anti-pattern é a situação na qual toda vez
que uma cópia de um determinado objeto é necessária
sua criação deve ser realizada, comprometendo,
possivelmente, o desempenho da aplicação e a
quantidade de memória para comportar um número
elevado de objetos.
Prototype
• Exemplo:
– Neste exemplo é mostrado uma hierarquia de classes
representando documentos de
formato ASCII e PDF que são criados através da
classe Cliente.
– A partir de duas instâncias prototípicas, ascii e pdf,
o método criarDocumento cria clones de
documentos de acordo com o tipo desejado.
– A tarefa de realizar a criação da instância é
implementada na classe Documento e herdada por
suas classes filhas, ASCII ePDF.
Prototype
• Exemplo:
Prototype - Código
• Icloneable.java:
public interface ICloneable {
public void clone();
}
Prototype - Código
• Documento.java:
abstract class Documento implements ICloneable {
protected Documento clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException ex) {
ex.printStackTrace();
}
return (Documento) clone;
}
}
Prototype - Código
• ASCII.java:
class ASCII extends Documento {
Prototype - Código
• PDF.java:
class PDF extends Documento {
Prototype - Código
• Cliente.java:
class Cliente {
static final int DOCUMENTO_TIPO_ASCII = 0;
static final int DOCUMENTO_TIPO_PDF = 1;
private Documento ascii = new ASCII();
private Documento pdf = new PDF();
Padrões Estruturais
• Os padrões estruturais vão se preocupar em como as
classes e objetos são compostos, ou seja, como é a sua
estrutura.
Padrões Estruturais
• Os padrões com escopo de classe utilizam a herança
para compor implementações ou interfaces.
Padrões Estruturais
• Adapter
• Bridge
• Composite
• Decorator
• Façade
• Flyweight
• Proxy
Padrões Comportamentais
• Os padrões comportamentais atuam sobre como
responsabilidades são atribuídas as entidades, ou seja,
qual o comportamento das entidades.
Padrões Comportamentais
• Padrões com escopo de classe utilizam herança para
realizar a distribuição do comportamento.
Padrões Comportamentais
• Chain of Responsibility
• Command
• Interpreter
• Iterator
• Mediator
• Memento
• Observer
• State
• Strategy
• Template Method
• Visitor
Unidade 2 – Padrões GoF
Padrões de Projetos de Software
Chain of Responsibility
Chain of Responsibility
• Apresentação:
Chain of Responsibility
• Aplicabilidade:
Chain of Responsibility
• Estrutura:
Chain of Responsibility
• Estrutura:
Chain of Responsibility
• Exemplo:
• Uma aplicação de e-commerce precisa se comunicar com
vários bancos diferentes para prover aos seus usuários
mais possibilidades de pagamentos, atingindo assim um
número maior de usuários e facilitando suas vidas.
Chain of Responsibility
• Exemplo:
public BancoA() {
super(IDBancos.bancoA);
}
@Override
protected void efetuaPagamento() {
System.out.println("Pagamento efetuado no banco A");
}
}
try {
bancos.efetuarPagamento(IDBancos.bancoC);
bancos.efetuarPagamento(IDBancos.bancoD);
bancos.efetuarPagamento(IDBancos.bancoA);
bancos.efetuarPagamento(IDBancos.bancoB);
} catch (Exception e) {
e.printStackTrace();
}
}}
Unidade 2 – Padrões GoF
Padrões de Projetos de Software
Command
Command
• Apresentação:
Command
• Aplicabilidade:
Command
• Aplicabilidade:
Command
• Estrutura:
Command – Código
• Loja.java:
public class Loja {
protected String nomeDaLoja;
Command – Código
• Exemplo:
Command – Código
• Loja.java:
public class Compra {
private static int CONTADOR_ID;
protected int idNotaFiscal;
protected String nomeDaLoja;
protected double valorTotal;
Command – Código
• Agora, aplicando o padrão!
Command
• Exemplo:
Command – Código
• PagamentoCommand.java:
public interface PagamentoCommand {
void processarCompra(Compra compra);
}
Command – Código
• PagamentoBoleto.java:
public class PagamentoBoleto implements PagamentoCommand {
@Override
public void processarCompra(Compra compra) {
System.out.println("Boleto criado!\n" + compra.getInfoNota());
}
Command
• Observação:
• O padrão tem um conceito muito simples, utiliza-
se apenas da herança para agrupar classes e
obrigar que todas tenham uma mesma interface
em comum.
Command
• Observação:
• A diferença básica é que no padrão Command
não existe a ideia de um “algoritmo” que será
executado.
• No padrão Template Method as subclasses
definem apenas algumas operações, sem alterar o
esqueleto de execução.
• O padrão Command não oferece uma maneira de
execução de suas subclasses, apenas garante que
todas executem determinada requisição.
Unidade 2 – Padrões GoF
Padrões de Projetos de Software
Interpreter
Interpreter
• Apresentação:
Interpreter
• Aplicabilidade:
Interpreter
• Estrutura:
Interpreter
• Descrição:
• AbstractExpression declara a operação comum a
todos os elementos na árvore de sintaxe abstrata,
enquanto TerminalExpression implementa tal
operação para um determinado elemento terminal (que
não pode ser definido em termos de outros elementos).
Interpreter
• Descrição:
Interpreter
• Exemplo:
Interpreter
• Exemplo:
Interpreter – Código
• Contexto.java:
public class Contexto {
protected String input;
protected int output;
Interpreter – Código
• NumeroRomanoInterpreter.java:
public abstract class NumeroRomanoInterpreter {
public void interpretar(Contexto contexto) {
if (contexto.getInput().length() == 0) {
return;
}
// Os valores nove e quatro são os únicos que possuem duas casas
// Ex: IV, IX
if (contexto.getInput().startsWith(nove())) {
adicionarValorOutput(contexto, 9);
consumirDuasCasasDoInput(contexto);
} else if (contexto.getInput().startsWith(quatro())) {
adicionarValorOutput(contexto, 4);
consumirDuasCasasDoInput(contexto);
} else if (contexto.getInput().startsWith(cinco())) {
adicionarValorOutput(contexto, 5);
consumirUmaCasaInput(contexto);
}
// Os valores de um são os únicos que repetem, ex: III, CCC, MMM
while (contexto.getInput().startsWith(um())) {
adicionarValorOutput(contexto, 1);
consumirUmaCasaInput(contexto);
}
}
Interpreter – Código
• NumeroRomanoInterpreter.java:
public abstract class NumeroRomanoInterpreter {
...
Interpreter – Código
• UmDigitoRomano.java:
public class UmDigitoRomano extends NumeroRomanoInterpreter {
@Override
public String um() {
return "I";
}
@Override
public String quatro() {
return "IV";
}
@Override
public String cinco() {
return "V";
}
@Override
public String nove() {
return "IX";
}
@Override
public int multiplicador() {
return 1;
} Unidade 2 – Padrões GoF
Padrões de Projetos de Software
Interpreter – Código
• DoisDigitoRomano.java:
public class DoisDigitosRomano extends NumeroRomanoInterpreter {
@Override
public String um() {
return "X";
}
@Override
public String quatro() {
return "XL";
}
@Override
public String cinco() {
return "L";
}
@Override
public String nove() {
return "XC";
}
@Override
public int multiplicador() {
return 10;
} Unidade 2 – Padrões GoF
Padrões de Projetos de Software
Interpreter – Código
• Cliente.java:
public static void main(String[] args) {
ArrayList interpretadores = new ArrayList();
interpretadores.add(new QuatroDigitosRomano());
interpretadores.add(new TresDigitosRomano());
interpretadores.add(new DoisDigitosRomano());
interpretadores.add(new UmDigitoRomano());
System.out.println(numRomano+"="+Integer.toString(contexto.getOutput()));
}
Iterator
Iterator
• Apresentação:
Iterator
• Aplicabilidade:
Iterator
• Estrutura:
Iterator
• Descrição:
• Collection é a interface comum que disponibiliza a
assinatura do método createIterator(), entre outros,
que deve ser implementado pelas classes descendentes
e cujas implementações permitem o percorrimento da
coleção de objetos (agregado).
Iterator
• Exemplo:
Iterator – Código
• Representação Simples:
ArrayList<Canal> arrayListDeCanais = new ArrayList<Canal>();
Canal[] matrizDeCanais = new Canal[5];
Iterator – Código
• Usando o Padrão:
Iterator – Código
• AgregadoDeCanais.java:
public interface AgregadoDeCanais {
IteradorInterface criarIterator();
}
Iterator – Código
• CanaisEsportes.java:
public class CanaisEsportes implements AgregadoDeCanais {
public CanaisEsportes() {
canais = new ArrayList<Canal>();
canais.add(new Canal("Esporte ao vivo"));
canais.add(new Canal("Basquete 2011"));
canais.add(new Canal("Campeonato Italiano"));
canais.add(new Canal("Campeonato Espanhol"));
canais.add(new Canal("Campeonato Brasileiro"));
}
@Override
public IteradorListaDeCanais criarIterator() {
return new IteradorListaDeCanais(canais);
}
}
Unidade 2 – Padrões GoF
Padrões de Projetos de Software
Iterator – Código
• Classe que utilizar Matriz:
@Override
public IteradorInterface criarIterator() {
return new IteradorMatrizDeCanais(canais);
}
Iterator – Código
• IteradorInterface.java:
public interface IteradorInterface {
void first();
void next();
boolean isDone();
Canal currentItem();
}
Iterator – Código
• IteradorListaDeCanais.java:
public class IteradorListaDeCanais implements IteradorInterface {
Iterator – Código
• IteradorListaDeCanais.java:
public class IteradorMatrizDeCanais implements IteradorInterface {
protected Canal[] lista;
protected int contador;
@Override
public void first() {
contador = 0;
}
@Override
public void next() {
contador++;
}
@Override
public boolean isDone() {
return contador == lista.length;
}
@Override
public Canal currentItem() {
if (isDone()) {
contador = lista.length - 1;
} else if (contador < 0) {
contador = 0;
}
return lista[contador];
} Unidade 2 – Padrões GoF
}
Padrões de Projetos de Software
Iterator – Código
• Cliente.java:
public static void main(String[] args) {
AgregadoDeCanais canaisDeEsportes = new CanaisEsportes();
System.out.println("Canais de Esporte:");
for (IteradorInterface it = canaisDeEsportes.criarIterator(); !it.isDone();
it.next()){
System.out.println(it.currentItem().nome);
}
Mediator
Mediator
• Apresentação:
Mediator
• Aplicabilidade:
Mediator
• Estrutura:
Mediator
• Descrição:
Mediator
• Exemplo:
Memento
Memento
• Apresentação:
Memento
• Aplicabilidade:
Memento
• Estrutura:
Memento
• Descrição:
Memento
• Exemplo:
• Editor de texto, com recurso de recuperação de estados
anteriores ao atual.
Observer
Observer
• Apresentação:
Observer
• Apresentação:
Observer
• Aplicabilidade:
Observer
• Aplicabilidade:
Observer
• Estrutura:
Observer
• Descrição:
Observer
• Exemplo:
State
State
• Apresentação:
State
• Aplicabilidade:
State
• Aplicabilidade (Cont). :
State
• Estrutura:
State
• Descrição:
State
• Descrição (Cont.):
State
• Exemplo:
• Gerenciar os vários estados de um personagens de
game. (Ex: Mario)
Strategy
Strategy
• Apresentação :
Strategy
• Aplicabilidade:
Strategy
• Aplicabilidade (Cont.):
Strategy
• Estrutura:
Strategy
• Descrição:
Strategy
• Descrição (Cont.):
Strategy
• Descrição (Cont.):
Strategy
• Exemplo:
Template Method
Template Method
• Apresentação:
Template Method
• Aplicabilidade:
Template Method
• Estrutura:
Template Method
• Descrição:
Template Method
• Descrição (Cont.):
Template Method
• Descrição (Cont.):
Template Method
• Exemplo:
• Ordenação de uma Playlist de MP3
Visitor
Visitor
• Apresentação:
Visitor
• Aplicabilidade:
Visitor
• Aplicabilidade (Cont.):
Visitor
• Estrutura:
Visitor
• Descrição:
Visitor
• Exemplo:
• Representação de Árvore Binária