Escolar Documentos
Profissional Documentos
Cultura Documentos
Design Patterns para Software - Java
Design Patterns para Software - Java
IPS-ESTSetbal
Padres de Desenho
ndice
Nota Prvia ................................................................................................................... 3
Historial........................................................................................................................ 4
Padres de Desenho GoF .............................................................................................. 5
Padres de Criao ..................................................................8
Abstract Factory (Fbrica Abstracta) ..................................................................... 8
Builder (Fabricante) ............................................................................................ 14
Factory Method (Mtodo-Fbrica)....................................................................... 19
Prototype (Prottipo)........................................................................................... 25
Singleton (Solitrio) ............................................................................................ 31
Padres Estruturais ................................................................ 34
Adapter (Adaptador) ........................................................................................... 34
Bridge (Ponte)..................................................................................................... 39
Composite (Composto)........................................................................................ 43
Decorator (Decorador) ........................................................................................ 47
Faade (Fachada) ................................................................................................ 51
Flyweight (Peso-Leve) ........................................................................................ 54
Proxy (Procurador).............................................................................................. 59
Padres de Comportamento .................................................... 63
Chain of Responsibility (Cadeia de Responsabilidade) ........................................ 63
Command (Comando) ......................................................................................... 67
Interpreter (Interpretador).................................................................................... 71
Iterator (Iterador)................................................................................................. 75
Mediator (Mediador) ........................................................................................... 79
Memento (Memria) ........................................................................................... 83
Observer (Observador) ........................................................................................ 87
State (Estado)...................................................................................................... 92
Strategy (Estratgia)............................................................................................ 98
Template Method (Mtodo-Modelo) ................................................................. 101
Visitor (Visitante) ............................................................................................. 104
Relaes entre Padres GoF .................................................. 109
Referncias ............................................................................................................... 110
Anacleto Correia
IPS-ESTSetbal
Padres de Desenho
Nota Prvia
O contedo deste documento resulta de compilao e tratamento de
elementos provenientes de diversas fontes, as quais se encontram
listadas nas Referncias.
Anacleto Correia
IPS-ESTSetbal
Padres de Desenho
Historial
Christopher Alexander descreve 250 padres de desenho de
arquitectura, no livro A Pattern Language: Towns, Buildings,
Construction. A descrio de um padro de desenho consiste na
apresentao e discusso de um determinado problema e na
descrio de uma soluo que sirva para diversos problemas que
possam ser encontrados e que se encaixem no mesmo padro.
De igual modo, no desenho de software, estudar padres de desenho
importante, porque:
Anacleto Correia
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
IPS-ESTSetbal
Classe
Padres de Desenho
De Criao
Factory Method
Objectivo
Estrutural
Comportamental
Adapter
Interpreter
Template Method
Adapter
Bridge
Composite
Decorator
Facade
Flyweigth
Proxy
Chain of Responsability
Command
Iterator
Mediator
Memento
Observer
State
Strategy
Visitor
Anacleto Correia
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
IPS-ESTSetbal
Padres de Desenho
Padres de Criao
So padres que tm a ver com a instanciao de objectos.
AbstractFactory
o Declara uma interface para operaes de criao de
produtos abstractos
ConcreteFactory
o Implementa as operaes de criao de objectos de
produtos concretos
AbstractProduct
o Declara uma interface para um objecto do tipo produto
Product
o Define um objecto do tipo produto a ser criado pela
correspondente fbrica concreta
o implementa a interface AbstractProduct
Client
o Utiliza as interfaces declaradas pelas classes
AbstractFactory e AbstractProduct
Anacleto Correia
IPS-ESTSetbal
Anacleto Correia
Padres de Desenho
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
10
IPS-ESTSetbal
Padres de Desenho
Exemplo
Anacleto Correia
11
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
12
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
13
IPS-ESTSetbal
Padres de Desenho
Builder (Fabricante)
Separa a construo de um objecto complexo da sua representao
para que o mesmo processo de construo possa criar representaes
diferentes.
O padro builder consiste em delegar numa classe especfica,
designada por Director, a tarefa de construir objectos complexos e
similares entre si. O cliente especifica ao director o que quer construir
e este ltimo ir providenciar a construo, chamando o construtor
adequado para cada situao. A utilizao deste padro
conveniente quando o processo de construo do objecto complexo
e passvel de futura alterao, de forma que o cliente no tenha de
saber como funciona, para no ficar acoplado.
Participantes:
As classes e/ou objectos que participam no padro so:
Builder
o Especifica uma interface abstracta de criao de
componentes de um objecto de Product
ConcreteBuilder
o Constri e monta as componentes de Product,
implementado a interface Builder
o Define e mantm referncia da representao (instncia
de Product) que cria
o Fornece uma interface para obteno do produto criado
Director
o Constri um objecto utilizando a interface Builder
Product
o Representa o objecto complexo a ser construdo.
ConcreteBuilder constri a representao interna do
produto e define o processo pelo qual montado.
o Inclui classes que definem as componentes constituintes,
incluindo as interfaces para montagem dos componentes
no produto acabado
Anacleto Correia
14
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
15
IPS-ESTSetbal
Padres de Desenho
Exemplo
import java.util.Collections;
import java.util.HashMap;
// padro Builder -- exemplo real
// Client
public class MainApp
{
public static void main(String[] args)
{
// Cria um concessionario com construtores de veiculos
Concessionario concessionario = new Concessionario();
VeiculoBuilder b1 = new ScooterBuilder();
VeiculoBuilder b2 = new AutomovelBuilder();
VeiculoBuilder b3 = new MotocicloBuilder();
// Constri e mostra veiculos
concessionario.Construct(b1);
b1.getVeiculo().mostrar();
concessionario.Construct(b2);
b2.getVeiculo().mostrar();
concessionario.Construct(b3);
b3.getVeiculo().mostrar();
}
}
// "Director"
class Concessionario
{
// Builder utiliza um conjunto complexo de passos
public void Construct(VeiculoBuilder veiculoBuilder)
Anacleto Correia
16
IPS-ESTSetbal
Padres de Desenho
{
veiculoBuilder.ConstroiEstrutura();
veiculoBuilder.ConstroiMotor();
veiculoBuilder.ConstroiRodas();
veiculoBuilder.ConstroiPortas();
}
}
// "Builder"
abstract class VeiculoBuilder
{
protected Veiculo veiculo;
public Veiculo getVeiculo()
{
return veiculo;
}
public abstract void ConstroiEstrutura();
public abstract void ConstroiMotor();
public abstract void ConstroiRodas();
public abstract void ConstroiPortas();
}
// "ConcreteBuilder1"
class MotocicloBuilder extends VeiculoBuilder
{
public void ConstroiEstrutura()
{
veiculo = new Veiculo("Motociclo");
veiculo.setCaracteristica("estrutura","Estrutura Motociclo");
}
public void ConstroiMotor()
{
veiculo.setCaracteristica("motor","500 cc");
}
public void ConstroiRodas()
{
veiculo.setCaracteristica("rodas","2");
}
public void ConstroiPortas()
{
veiculo.setCaracteristica("portas","0");
}
}
// "ConcreteBuilder2"
class AutomovelBuilder extends VeiculoBuilder
{
public void ConstroiEstrutura()
{
veiculo = new Veiculo("Automovel");
veiculo.setCaracteristica("estrutura","Estrutura Automovel");
}
public void ConstroiMotor()
{
veiculo.setCaracteristica("motor","2500 cc");
}
public void ConstroiRodas()
{
veiculo.setCaracteristica("rodas","4");
}
public void ConstroiPortas()
{
veiculo.setCaracteristica("portas","4");
}
Anacleto Correia
17
IPS-ESTSetbal
Padres de Desenho
}
// "ConcreteBuilder3"
class ScooterBuilder extends VeiculoBuilder
{
public void ConstroiEstrutura()
{
veiculo = new Veiculo("Scooter");
veiculo.setCaracteristica("estrutura","Estrutura Scooter");
}
public void ConstroiMotor()
{
veiculo.setCaracteristica("motor","50 cc");
}
public void ConstroiRodas()
{
veiculo.setCaracteristica("rodas","2");
}
public void ConstroiPortas()
{
veiculo.setCaracteristica("portas","0");
}
}
// "Product"
class Veiculo
{
private String tipo;
private HashMap componentes = new HashMap();
// Constructor do Veiculo
public Veiculo(String tipo)
{
this.tipo = tipo;
}
public Object getCaracteristica(String key){
return componentes.get(new Integer(key.hashCode()));
}
public void setCaracteristica(String key, String value){
componentes.put(new Integer(key.hashCode()),value);
}
public void mostrar()
{
System.out.println("\n---------------------------");
System.out.println(" Tipo Veiculo: "+ tipo);
System.out.println(" Estrutura : " + componentes.get(new
Integer("estrutura".hashCode())));
System.out.println(" Motor : " + componentes.get(new
Integer("motor".hashCode())) );
System.out.println(" #Rodas: " + componentes.get(new
Integer("rodas".hashCode())) );
System.out.println(" #Portas : " + componentes.get(new
Integer("portas".hashCode())) );
}
}
Anacleto Correia
18
IPS-ESTSetbal
Padres de Desenho
Product
o Define uma interface de objectos que o mtodo-fbrica
cria
ConcreteProduct
o Implementa a interface do Product
Creator
o Declara o mtodo-fbrica, que retorna um objecto do tipo
Product. Creator pode tambm definir uma
implementao por omisso do mtodo-fbrica, que
retorna por omisso um objecto ConcreteProduct.
o Pode evocar o mtodo-fbrica para criar o objecto
Product.
ConcreteCreator
o Sobre-escreve o mtodo-fbrica para retornar uma
instncia de ConcreteProduct.
Anacleto Correia
19
IPS-ESTSetbal
Padres de Desenho
Exemplo
// ------------------------ Factory Method
// Define uma interface para a criao de objectos, mas deixa as
// subclasses decidirem que classe instanciam.
// "Product"
abstract class Product {}
// "ConcreteProductA"
class ConcreteProductA extends Product {}
// "ConcreteProductB"
class ConcreteProductB extends Product {}
// "Creator"
abstract class Creator
{
// Methods
abstract public Product FactoryMethod();
}
// "ConcreteCreatorA"
class ConcreteCreatorA extends Creator
{
// Methods
public Product FactoryMethod()
{
return new ConcreteProductA();
}
}
// "ConcreteCreatorB"
class ConcreteCreatorB extends Creator
{
Anacleto Correia
20
IPS-ESTSetbal
Padres de Desenho
// Methods
public Product FactoryMethod()
{
return new ConcreteProductB();
}
}
// "Client"
public class Factory_Estrutural {
// Main method
public static void main (String[] args) {
// Create director and builders
Creator ca = new ConcreteCreatorA();
Product pa = ca.FactoryMethod();
System.out.println ("Created " + pa);
Creator cb = new ConcreteCreatorB();
Product pb = cb.FactoryMethod();
System.out.println ("Created " + pb);
}
}
Anacleto Correia
21
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
22
IPS-ESTSetbal
Padres de Desenho
// ConcreteProduct
class SummaryPage
extends Page {}
// ConcreteProduct
class BibliographyPage
extends Page {}
// ConcreteProduct
class ResultsPage
extends Page {}
// ConcreteProduct
class ConclusionPage
extends Page {}
// Creator
abstract class Document{
protected ArrayList pages = new ArrayList();
public Document() {
this.CreatePages();
}
public ArrayList getPages() {
return pages;
}
public String toString() {
return this.getClass().getName();
}
abstract public void CreatePages();
}
// ConcreteCreator
class Resume extends Document{
public void CreatePages() {
pages.add (new SkillsPage());
pages.add (new EducationPage());
pages.add (new ExperiencePage());
}
}
// ConcreteCreator
class Report extends Document
{
public void CreatePages()
{
pages.add (new IntroductionPage());
pages.add (new ResultsPage());
pages.add (new ConclusionPage());
pages.add (new SummaryPage());
pages.add (new BibliographyPage());
}
}
// Client
class Test {
public static void main( String[] args )
{
Document[] docs = new Document[ 2 ];
docs[0] = new Resume(); //Cria ConcreteCraetorA
docs[1] = new Report();// Cria ConcreteCreator B
for( int i=0; i<docs.length;i++)
{
System.out.println( "\n" + docs[i] + " ------- " );
ArrayList p =((Document)docs[i]).getPages();
for( int j=0; j<p.size();j++)
{
System.out.println(" " + p.get(j));
}
Anacleto Correia
23
IPS-ESTSetbal
Padres de Desenho
}
}
}
/*
Resume ------SkillsPage
EducationPage
ExperiencePage
Report ------IntroductionPage
ResultsPage
ConclusionPage
SummaryPage
BibliographyPage
*/
Anacleto Correia
24
IPS-ESTSetbal
Padres de Desenho
Prototype (Prottipo)
Especifica os tipos de objectos a criar usando uma instncia-prottipo
e cria novos objectos copiando este prottipo.
O padro Prototype consiste pois em construir objectos a partir de
outros j existentes, aproveitando suas caractersticas. O mtodo
clone() da classe Object em Java um exemplo deste padro.
Participantes:
As classes e/ou objectos que participam no padro so:
Prototype
o Declara uma interface para se autoclonar
ConcretePrototype
o Implementa uma interface para se autoclonar
Client
o Cria um novo objecto pedindo ao prottipo para se
autoclonar
Exemplo
// Prototype pattern
import java.lang.Cloneable;
// Client test application
public class ClientApp
{
public static void main(String[] args)
{
// Create first instance and clone it
Prototype p1 = new ConcretePrototype1("I");
Anacleto Correia
25
IPS-ESTSetbal
Padres de Desenho
26
IPS-ESTSetbal
Padres de Desenho
Exemplo
/*
Demonstrao do padro Prototype em que as novas cores
so criadas a partir de cpia das pr-existentes do mesmo tipo
*/
// Padro Prototype -- examplo real
import java.util.Collections;
import java.lang.Cloneable;
import java.util.HashMap;
// ClientApp - applicao de teste
public class ClientApp {
public static void main(String[] args) {
GestorCor gestorCor = new GestorCor();
// inicializar com cores standard
gestorCor.setCaracteristica("vermelha", new Cor(255, 0, 0));
gestorCor.setCaracteristica("verde", new Cor(0, 255, 0));
gestorCor.setCaracteristica("azul", new Cor(0, 0, 255));
// adicionar cores personalizadas
gestorCor.setCaracteristica("zangada", new Cor(255, 54, 0));
gestorCor.setCaracteristica("paz", new Cor(128, 211, 128));
gestorCor.setCaracteristica("chama", new Cor(211, 34, 20));
Cor cor;
// seleco de cores
String name = "vermelha";
cor = (Cor) gestorCor.getCaracteristica(new
Integer(name.hashCode())).clone();
name = "paz";
cor = (Cor) gestorCor.getCaracteristica(new
Integer(name.hashCode())).clone();
name = "chama";
cor = (Cor) gestorCor.getCaracteristica(new
Integer(name.hashCode())).clone();
}
Anacleto Correia
27
IPS-ESTSetbal
Padres de Desenho
}
// "Prototype"
abstract class CorPrototype
implements Cloneable {
public abstract Object clone();
}
// "ConcretePrototype"
class Cor
extends CorPrototype {
private int vermelha;
private int verde;
private int azul;
// Constructor
public Cor(int vermelha, int verde, int azul) {
this.vermelha = vermelha;
this.verde = verde;
this.azul = azul;
}
// Criao de uma cpia superficial
public Object clone() {
System.out.println(
"Clonagem cor RGB: " + vermelha + ", " + verde + ", " + azul);
return (CorPrototype)new Cor(vermelha, verde, azul);
}
}
// Prototype manager
class GestorCor {
private HashMap componentes = new HashMap();
HashMap cors = new HashMap();
public CorPrototype getCaracteristica(Integer name) {
return (CorPrototype) cors.get(new Integer(name.hashCode()));
}
public void setCaracteristica(String name, Cor value) {
cors.put(new Integer(name.hashCode()), value);
}
}
// Clonagem cor RGB: 255, 0, 0
// Clonagem cor RGB: 128, 211, 128
// Clonagem cor RGB: 211, 34, 20
Anacleto Correia
28
IPS-ESTSetbal
Padres de Desenho
Exemplo
Anacleto Correia
29
IPS-ESTSetbal
Padres de Desenho
String colherName;
public void setColherName(String colherName) {
this.colherName = colherName;
}
public String getColherName() {return this.colherName;}
public Object clone()
{
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
System.err.println("AbstractColher is not Cloneable");
}
return object;
}
}
// AbstractGarfo.java
// Two of Two Prototypes
abstract class AbstractGarfo implements Cloneable
{
String garfoName;
public void setGarfoName(String garfoName) {this.garfoName = garfoName;}
public String getGarfoName() {return this.garfoName;}
public Object clone()
{
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
System.err.println("AbstractGarfo is not Cloneable");
}
return object;
}
}
// ColherSopa.java
// One of Two Concrete Prototypes extending the AbstractColher Prototype
class ColherSopa extends AbstractColher
{
public ColherSopa()
{
setColherName("Colher Sopa");
}
}
// SaladaColher.java
// Two of Two Concrete Prototypes extending the AbstractColher Prototype
class SaladaColher extends AbstractColher
{
public SaladaColher()
{
setColherName("Colher Salada");
}
}
// GarfoSalada.java
// The Concrete Prototype extending the AbstractGarfo Prototype
class GarfoSalada extends AbstractGarfo
{
public GarfoSalada()
{
setGarfoName("Garfo Salada");
}
}
//
//
//
//
//
//
//
//
Anacleto Correia
30
IPS-ESTSetbal
Padres de Desenho
Singleton (Solitrio)
Garante que uma classe tenha uma nica instncia e fornece um
ponto global de acesso instncia.
Este padro visa garantir que uma classe possui apenas uma
instncia. Assim, um singleton possui construtor privado (ou
protegido) e um mtodo obterInstancia(), que deve ser
sincronizado para que duas threads no o executem ao mesmo
tempo. Quando executado pela primeira vez, cria a instncia e gravaa numa propriedade static da classe, retornando esta mesma
propriedade sempre que requsitada pelo obterInstancia().
Participantes:
As classes e/ou objectos que participam no padro so:
Singleton
o Define o mtodo de classe Instance (ou
obterInstancia()) que permite aos clientes acederem
sua nica instncia.
o Responsvel por criar e manter a sua nica instncia.
Anacleto Correia
31
IPS-ESTSetbal
Padres de Desenho
Exemplo
// ---------------------------- Padro Singleton
// classe declarada como final impede seu uso atravs de herana
// "Singleton"
public final class SingletonImpl {
// campo esttico armazena a nica instncia desta classe
private static SingletonImpl instance = null;
// construtores devem ser privados para impedir uso externo
private SingletonImpl() {
// campos da classe podem ser
// normalmente inicializados
}
// retorna o nico objeto que pode ser instanciado
public static SingletonImpl getInstance() {
if (instance==null) {
// instanciao ocorre apenas se um objecto for solicitado
instance = new SingletonImpl();
}
return instance;
}
}
// "Cliente"
public class UsoDoSingletonImpl {
// ............
SingletonImpl obj;
// ............
obj = SingletonImpl.getInstance();
// ............
}
Exemplo de criao de uma instncia global usando o Padro Singleton
// Singleton para variveis globais de uma aplicao
public final class GlobalVars {
// campo esttico para referncia nica
private static GlobalVars instance = null;
// campos da classe
public int inteiro;
public float real;
// construtor privados
private GlobalVars() {
// campos da classe podem ser
// normalmente inicializados
inteiro = 0;
real = -1;
}
Anacleto Correia
32
IPS-ESTSetbal
Padres de Desenho
Duplicado
inteiro = -50
real = 30.69
inteiro = 20
real = -10.85
1/a Instancia
inteiro = 20
real = -10.85
*/
Anacleto Correia
33
IPS-ESTSetbal
Padres de Desenho
Padres Estruturais
Padres que tm a ver com a composio de classes ou objectos
Adapter (Adaptador)
Converte a interface de uma classe numa outra interface que os
clientes possam utilizar. O padro Adapter permite que classes
trabalhem em conjunto apesar de possurem partida interfaces
incompatveis.
Em diversas ocasies, temos uma classe X que utiliza atravs do seu
mtodo x() uma outra classe Y. No entanto, na interface da classe Y,
o mtodo possui o nome y(). Para que as duas classes comuniquem,
necessrio que haja um adaptador entre elas. Assim, cria-se a
classe Adapter que implementa a interface esperada por X, evocando
o mtodo apropriado de Y.
Dois exemplos clssicos de adapter existem no API J2SE. No pacote
java.awt.event existem vrios adaptadores (MouseAdapter,
KeyAdapter, ). As classes-envolventes (wrapper classes: Integer,
Long, ) tambm so adaptadoras, pois adaptam os tipos primitivos
para os casos em que s so aceites objectos (nas coleces, por
exemplo).
Participantes:
As classes e/ou objectos que participam no padro so:
Target
o Define o domnio especfico da interface que Client ir
utilizar.
Adapter
o Adapta a interface de Adaptee interface de Target.
Adaptee
o Define uma interface existente que necessita de ser
adaptada.
Client
o Colabora com objectos que estejam conforme a interface
de Target.
Anacleto Correia
34
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
35
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro Adapter
// "Target"
class Composto {
protected String nome;
protected float pontoEbulicao;
protected float pontoLiquidificacao;
protected double pesoMolecular;
protected String formulaMolecular;
// Constructor
public Composto(String nome) {
this.nome = nome;
}
public void mostrar() {
System.out.println("\nComposto: " + nome + " ------ ");
}
}
// "Adapter"
class CompostoRico
extends Composto {
private BaseBadosQuimica banco;
// Constructor
public CompostoRico(String nome) {
super(nome);
}
public void mostrar() {
// Adaptee
banco = new BaseBadosQuimica();
pontoEbulicao = banco.getPontoCritico(nome, "E");
pontoLiquidificacao = banco.getPontoCritico(nome, "L");
pesoMolecular = banco.getPesoMolecular(nome);
formulaMolecular = banco.getEstruturaMolecular(nome);
super.mostrar();
Anacleto Correia
36
IPS-ESTSetbal
System.out.println("
System.out.println("
System.out.println("
System.out.println("
Padres de Desenho
Formula:
Peso : "
Ponto de
Ponto de
" + formulaMolecular);
+ pesoMolecular);
Liquidificao: " + pontoLiquidificacao);
Ebulio: " + pontoEbulicao);
}
}
// "Adaptee"
class BaseBadosQuimica {
// A Base de Dados com 'API legada'
public float getPontoCritico(String compound, String point) {
float temperatura = 0.0F;
// Ponto de Liquidificao
if (point.compareTo("L") == 0) {
switch (compound.toLowerCase().charAt(1)) {
case 'g':
temperatura = 0.0F;
break; // "gua"
case 'e':
temperatura = 5.5F;
break; //"benzina"
case 'l':
temperatura = -114.1F;
break; //"alcool"
}
}
// Ponto de ebulio
else {
switch (compound.toLowerCase().charAt(1)) {
case 'g':
temperatura = 100.0F;
break; // "gua"
case 'e':
temperatura = 80.1F;
break; //"benzina"
case 'l':
temperatura = 78.3F;
break; //"alcool"
}
}
return temperatura;
}
public String getEstruturaMolecular(String compound) {
String structure = "";
switch (compound.toLowerCase().charAt(1)) {
case 'g':
structure = "H20";
break; // "gua"
case 'e':
structure = "C6H6";
break; //"benzina"
case 'l':
structure = "C2H6O2";
break; //"alcool"
}
return structure;
}
public double getPesoMolecular(String compound) {
double peso = 0.0;
switch (compound.toLowerCase().charAt(1)) {
case 'g':
peso = 18.015;
break; // "gua"
case 'e':
peso = 78.1134;
break; //"benzina"
case 'l':
peso = 46.0688;
break; //"alcool"
}
return peso;
}
}
Anacleto Correia
37
IPS-ESTSetbal
Padres de Desenho
// aplicao Client
class AdapterPat {
public static void main(String[] args) {
// componente qumico no adaptado
Composto coisa = new Composto("Desconhecido");
coisa.mostrar();
// componente qumico adaptado
Composto agua = new CompostoRico("Agua");
agua.mostrar();
Composto benzina = new CompostoRico("Benzina");
benzina.mostrar();
Composto alcool = new CompostoRico("Alcool");
alcool.mostrar();
}
}
/*
Composto: Desconhecido -----Composto: Agua -----Formula: H20
Peso : 18.015
Ponto de Liquidificao: 0.0
Ponto de Ebulio: 100.0
Composto: Benzina -----Formula: C6H6
Peso : 78.1134
Ponto de Liquidificao: 5.5
Ponto de Ebulio: 80.1
Composto: Alcool -----Formula: C2H6O2
Peso : 46.0688
Ponto de Liquidificao: -114.1
Ponto de Ebulio: 78.3
*/
Anacleto Correia
38
IPS-ESTSetbal
Padres de Desenho
Bridge (Ponte)
Desacopla uma abstraco da sua implementao de forma que as
duas possam variar de forma independente.
Por exemplo, num sistema acadmico se tiver uma interface
Estudante e duas classes que efectuem a sua implementao: uma
para armazenamento dos dados em XML e outra atravs de
serializao em ficheiro. Em princpio no teramos problemas com
esta abordagem. Mas se pretender criar subinterfaces de Estudante:
EstudanteBacharelato, EstudanteMestrado, EstudanteDoutoramento,
etc. ento no se teria apenas duas implementaes, mas seis!
Separando o modelo da persistncia e criando uma ponte (bridge)
entre eles, o problema ficaria resolvido.
Anacleto Correia
39
IPS-ESTSetbal
Padres de Desenho
Exemplo
// --------------- Bridge
// Separar a abstraco da sua implementao para que cada uma
// possa variar independentemente.
//Abstraction
class Pilha {
protected ImplementacaoPilha pi;
public Pilha(String s) {
if (s.equals("java")) {
pi = new PilhaJava();
}
else {
pi = new PilhaArray();
}
}
public Pilha() {
this("java");
}
public void push(int in) {
pi.push(new Integer(in));
}
public int pop() {
return ( (Integer) pi.pop()).intValue();
}
public boolean isEmpty() {
return pi.empty();
}
}
//RefinedAbstraction
class PilhaCrescente
extends Pilha {
private int _totalRejeitados = 0;
public PilhaCrescente() {
Anacleto Correia
40
IPS-ESTSetbal
Padres de Desenho
super("java");
}
public PilhaCrescente(String s) {
super(s);
}
public int reportaRejeitados() {
return _totalRejeitados;
}
public void push(int in) {
if (!pi.empty() && in > ( (Integer) pi.peek()).intValue()) {
_totalRejeitados++;
}
else {
pi.push(new Integer(in));
}
}
}
// Implementor
interface ImplementacaoPilha {
Object push(Object o);
Object peek();
boolean empty();
Object pop();
}
// ConcreteImplementorA
class PilhaJava extends java.util.Stack implements
ImplementacaoPilha{}
// ConcreteImplementorB
class PilhaArray implements ImplementacaoPilha {
private Object[] _items = new Object[20];
private int _total = -1;
public Object push(Object o) { return _items[++_total] = o; }
public Object peek() { return _items[_total]; }
public Object pop() {return _items[_total--]; }
public boolean empty() { return _total == -1;}
}
// Client
class TestBridge {
public static void main(String[] args) {
Pilha[] pilhas = {
new Pilha("java"), new PilhaCrescente("java"),
new Pilha("meu"),new PilhaCrescente("meu") };
for (int i = 0, num; i < 20; i++) {
num = (int) (Math.random() * 1000) % 40;
for (int j = 0; j < pilhas.length; j++) {
pilhas[j].push(num);
}
}
for (int i = 0, num; i < pilhas.length; i++) {
while (!pilhas[i].isEmpty()) {
System.out.print(pilhas[i].pop() + " ");
}
System.out.println();
}
System.out.println("O total de elementos rejeitados "
+ ( (PilhaCrescente) pilhas[1]).reportaRejeitados());
}
}
/*
29 28 38 8 0 31 3 15 18 5 15 34 23 3 35 38 19 32 4 21
0 3 3 4 21
Anacleto Correia
41
IPS-ESTSetbal
Padres de Desenho
29 28 38 8 0 31 3 15 18 5 15 34 23 3 35 38 19 32 4 21
0 3 3 4 21
O total de elementos rejeitados 15
*/
Anacleto Correia
42
IPS-ESTSetbal
Padres de Desenho
Composite (Composto)
Compe objectos em estruturas de rvore para representar
hierarquias parte-todo. O padro Composite permite que os clientes
tratem objectos individuais e composies de objectos de forma
uniforme.
Consiste em agrupar componentes em conjuntos e considerar o
conjunto como se fosse tambm um componente com a mesma
interface, dispondo todos em rvore para tratamento uniforme. Por
exemplo, supondo que existem vrios componentes C que possuem
um mtodo c() que se pretende executar. Pode-se agrupar todos
estes componentes num nico objecto Composite, que implementa a
interface do componente C, com o mtodo c() em Composite, a
evocar o mtodo c() de todos os componentes a agrupados. Como
Composite implementa a mesma interface de C, pode-se agrupar
composies dentro de composies, formando uma rvore.
Participantes:
As classes e/ou objectos que participam no padro so:
Component
o Declara a interface para objectos na composio.
o Implementa conforme apropriado, o comportamento por
omisso da interface comum a todas as classes.
o Declara uma interface para acesso e gesto dos
componentes filhos.
o (opcional) define uma interface para acesso ao
componente pai, na estrutura recursiva, e implementa-a
caso apropriado.
Leaf
o Representa os objectos folha na composio. Uma folha
no tem filhos.
o Define o comportamento dos objectos primitivos na
composio.
Composite
o Define o comportamento dos componentes que tm
filhos.
o Armazena os componentes filhos.
o Implementa os mtodos relacionados com os filhos, na
interface Component.
Client
o Manipula objectos na composio atravs da interface
Component.
Anacleto Correia
43
IPS-ESTSetbal
Anacleto Correia
Padres de Desenho
44
IPS-ESTSetbal
Padres de Desenho
Exemplo
//COMPOSITE
interface Componente {void escreve();}
class Folha implements Componente {
private int _valor;
public Folha(int val) { _valor = val; }
public void escreve() {
System.out.print(_valor + " ");
}
}
abstract class No implements Componente {
private Componente[] _filhos = new Componente[9];
private int _total = 0;
private int _valor;
public No(int val) { _valor = val; }
public void add(Componente c) { _filhos[_total++] = c; }
public void escreve() {
System.out.print(_valor + " ");
for (int i=0; i < _total; i++) {
_filhos[i].escreve();
}
}
}
class Linha extends No {
public Linha(int val) { super(val); }
public void escreve() {
System.out.print("Linha");
super.escreve();
}
Anacleto Correia
45
IPS-ESTSetbal
Padres de Desenho
}
class Coluna extends No {
public Coluna(int val) { super(val); }
public void escreve() {
System.out.print("Coluna");
super.escreve();
}
}
public class CompostoDemo {
public static void main(String[] args) {
Componente primei = new Linha(1);
Componente segund = new Coluna(2);
Componente tercei = new Coluna(3);
Componente quarto = new Linha(4);
Componente quinto = new Linha(5);
primei.add(segund);
primei.add(tercei);
tercei.add(quarto);
tercei.add(quinto);
primei.add(new Folha(6));
segund.add(new Folha(7));
tercei.add(new Folha(8));
quarto.add(new Folha(9));
quinto.add(new Folha(10));
primei.escreve();
}
}
// Linha1 Coluna2 7 Coluna3 Linha4 9 Linha5 10 8 6
Anacleto Correia
46
IPS-ESTSetbal
Padres de Desenho
Decorator (Decorador)
Adiciona responsabilidades de forma dinmica a um objecto. Os
Decoradores fornecem uma alternativa flexvel herana para
estender funcionalidades.
O padro Decorator permite assim, estender as funcionalidades de
uma classe em tempo de execuo. A ideia que uma classe possui
um determinado mtodo que retorna um resultado, mas podemos-lhe
acoplar vrias outras classes, que iro realizar certo processamento
antes ou depois da operao, retornando o valor apenas no final.
Dois exemplos: filtros do API Servlet e interceptores do Xwork. No
segundo caso, quando se acede uma aco do Xwork pode-se
configurar uma srie de interceptores que iro interceptar a aco
antes e depois da sua execuo. Os interceptores estendem a
funcionalidade da aco e, atravs de configurao XML, podemos
dizer que interceptores executar ou no, sem necessidade de
recompilar o cdigo.
Participantes:
As classes e/ou objectos que participam no padro so:
Component
o Define a interface dos objectos que podem ter
responsabilidades adicionadas de forma dinmica.
ConcreteComponent
o Define um objecto ao qual mais responsabilidades podem
ser adicionadas.
Decorator
o Mantm a referncia para um objecto Component e
define a interface que est conforme a interface
Component.
ConcreteDecorator
o Adiciona responsabilidades ao componente.
Anacleto Correia
47
IPS-ESTSetbal
Anacleto Correia
Padres de Desenho
48
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro Decorator
// Componente
interface Componente { void desenha(); }
// ConcreteComponent
class Texto implements Componente {
private int comprimento, altura;
public Texto(int c, int a) {
comprimento = c; altura = a;
}
public void desenha() {
System.out.println("Texto: " + comprimento +
", " + altura);
}
}
// Decorator
abstract class Decorador implements Componente {
private Componente obj;
public Decorador(Objecto o) { obj = o; }
public void desenha() { obj.desenha(); }
}
// ConcreteDecoratorA
class Borda extends Decorador {
public Borda(Componente o) { super(o); }
public void desenha() {
Anacleto Correia
49
IPS-ESTSetbal
Padres de Desenho
super.desenha();
System.out.println(" DecoraoBorda");
}
}
// ConcreteDecoratorB
class Cerca extends Decorador {
public Cerca(Componente o) { super(o); }
public void desenha() {
super.desenha();
System.out.println(" DecoraoCerca");
}
}
// Client
public class DecoratorPattern {
public static void main(String[] args) {
Componente obj = new Borda(
new Borda(
new Cerca(
new Texto(80,24))));
obj.desenha();
}
}
// Texto: 80, 24
// DecoraoCerca
// DecoraoBorda
// DecoraoBorda
Anacleto Correia
50
IPS-ESTSetbal
Padres de Desenho
Faade (Fachada)
Fornece uma interface unificada de alto-nvel, para acesso a um
conjunto de funcionalidades de um subsistema. O padro Faade ao
definir a interface de alto nvel torna o subsistema mais fcil de usar.
Faade uma classe que agrupa na sua interface acessos a mtodos
que so executados por diversas outras classes, servindo de fachada
a esses mtodos, de forma que, as demais classes no necessitem de
ser conhecidas pelos objectos clientes. Uma verso especial de
Faade na qual todos os mtodos so estticos designada por
Utility. frequente utilizar este padro em classes de aplicaes.
Dependendo do caso de utilizao que for ser implementado, cria-se
uma classe para cada caso de utilizao, uma para o pacote (que
fachada das classes que implementam os casos) e uma para toda a
aplicao, que fornece acesso s classes dos pacotes. Esta ltima
armazenada em sesso para que o utilizador tenha acesso, atravs
dela, a todas as funcionalidades do sistema.
Participantes:
As classes e/ou objectos que participam no padro so:
Facade
o Sabe que classes do subsistema so responsveis pelo
pedido.
o Delega os pedidos do cliente nos objectos apropriados do
subsistema.
classes do Subsistema
o Implementam as funcionalidades do subsistema.
o Levam a cabo o trabalho atribudo ao objecto Facade.
o No tm conhecimento do objecto Facade e no guardam
dele qualquer referncia.
Anacleto Correia
51
IPS-ESTSetbal
Padres de Desenho
Exemplo
// aplicao Cliente
public class patFacade {
public static void main(String[] args) {
// Facade
PedidoEmprestimo pedidoEmprestimo = new PedidoEmprestimo();
// Avalia se o cliente eligvel para obteno de emprstimo
Cliente cliente = new Cliente("Ana Silva");
boolean eligivel = pedidoEmprestimo.ehEligivel(cliente, 125000);
System.out.println("\nEmprstimo de " + cliente.getName() +
" foi " + (eligivel ? "Aprovado" :
"Rejeitado"));
}
}
// "Subsistema ClassA"
class Banco {
public boolean temPoupancasSuficientes(Cliente c, int amount) {
System.out.println("Verificar poupanas de " + c.getName());
return true;
}
}
// "Subsistema ClassB"
class Credito {
public boolean temCredito(Cliente c) {
System.out.println("Verificar credito de " + c.getName());
return true;
}
}
// "Subsistema ClassC"
class Emprestimo {
public boolean naoTemEmprestimos(Cliente c) {
Anacleto Correia
52
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
53
IPS-ESTSetbal
Padres de Desenho
Flyweight (Peso-Leve)
Utiliza a partilha para dar suporte eficiente utilizao de um grande
nmero de objectos de pequena granularidade.
Flyweight til no caso de se ter um pequeno conjunto de objectos
imutveis que so utilizados muitas vezes em diferentes locais do
sistema. Em vez de permitir que inmeras instncias destes objectos
sejam construdas indiscriminadamente, forma-se uma pool de
objectos que sero utilizados nas diversas situaes em que so
necessrios. importante, no entanto, garantir que os objectos so
realmente imutveis, ou o padro no poder ser aplicado.
Participantes:
As classes e/ou objectos que participam no padro so:
Flyweight
o Declara uma interface atravs da qual os flyweights
podem receber e actuar em estado extrnseco.
ConcreteFlyweight
o Implementa a interface Flyweight e adiciona
armazenamento para o estado intrnseco, caso haja. Um
objecto ConcreteFlyweight deve ser partilhado. Qualquer
estado que armazene deve ser intrnseco, isto , deve ser
independente do contexto do objecto ConcreteFlyweight.
UnsharedConcreteFlyweight
o Nem todas as subclasses Flyweight tm que ser
partilhadas. A interface Flyweight permite a partilha, mas
no a obriga. comum que os objectos
UnsharedConcreteFlyweight tenham objectos
ConcreteFlyweight como filhos num determinado nvel da
estrutura do objecto flyweight.
FlyweightFactory
o Cria e gere objectos flyweight
o Assegura que os flyweights so apropriadamente
partilhados. Quando um cliente solicita um flyweight, os
objectos FlyweightFactory fornecem uma instncia
existente ou criam uma, caso no exista.
Client
o Mantm referncia(s) para flyweight(s).
o Calcula ou armazena o estado extrnseco do(s)
flyweight(s).
Anacleto Correia
54
IPS-ESTSetbal
Anacleto Correia
Padres de Desenho
55
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro Flyweight
import java.util.HashMap;
// aplicao Cliente
public class patFlyweigh {
public static void main(String[] args) {
// Construir um documento com texto
String documento = "AAZZBBZB";
char[] chars = documento.toCharArray();
CaracterFabrica f = new CaracterFabrica();
// estado extrnseco
int apontadorTamanho = 10;
// Para cada carcter usar um objecto flyweight
for (int i = 0; i < chars.length; i++) {
apontadorTamanho++;
Caracter caracter = f.getCaracter(chars[i]);
caracter.mostrar(apontadorTamanho);
}
}
}
// "FlyweightFactory"
class CaracterFabrica {
private HashMap characters = new HashMap();
public Caracter getCaracter(char key) {
// Uses "lazy initialization"
Caracter caracter = (Caracter) characters.get(new Character(key));
if (caracter == null) {
switch (key) {
case 'A':
caracter = new CaracterA();
Anacleto Correia
56
IPS-ESTSetbal
Padres de Desenho
break;
case 'B':
caracter = new CaracterB();
break;
//...
case 'Z':
caracter = new CaracterZ();
break;
}
characters.put(new Character(key), caracter);
}
return caracter;
}
}
// "Flyweight"
abstract class Caracter {
protected char simbolo;
protected int comprimento;
protected int altura;
protected int ascendente;
protected int descendente;
protected int apontadorTamanho;
public abstract void mostrar(int apontadorTamanho);
}
// "ConcreteFlyweight"
class CaracterA
extends Caracter {
// Constructor
public CaracterA() {
this.simbolo = 'A';
this.altura = 100;
this.comprimento = 120;
this.ascendente = 70;
this.descendente = 0;
}
public void mostrar(int apontadorTamanho) {
this.apontadorTamanho = apontadorTamanho;
System.out.println(this.simbolo +
" (Tamanho " + this.apontadorTamanho + ")");
}
}
// "ConcreteFlyweight"
class CaracterB
extends Caracter {
// Constructor
public CaracterB() {
this.simbolo = 'B';
this.altura = 100;
this.comprimento = 140;
this.ascendente = 72;
this.descendente = 0;
}
public void mostrar(int apontadorTamanho) {
this.apontadorTamanho = apontadorTamanho;
System.out.println(this.simbolo +
Anacleto Correia
57
IPS-ESTSetbal
Padres de Desenho
" (Tamanho " + this.apontadorTamanho + ")");
}
}
// ... C, D, E, etc.
// "ConcreteFlyweight"
class CaracterZ
extends Caracter {
// Construtor
public CaracterZ() {
this.simbolo = 'Z';
this.altura = 100;
this.comprimento = 100;
this.ascendente = 68;
this.descendente = 0;
}
public void mostrar(int apontadorTamanho) {
this.apontadorTamanho = apontadorTamanho;
System.out.println(this.simbolo +
" (Tamanho " + this.apontadorTamanho + ")");
}
}
/*
A (Tamanho
A (Tamanho
Z (Tamanho
Z (Tamanho
B (Tamanho
B (Tamanho
Z (Tamanho
B (Tamanho
*/
11)
12)
13)
14)
15)
16)
17)
18)
Anacleto Correia
58
IPS-ESTSetbal
Padres de Desenho
Proxy (Procurador)
Fornece um objecto procurador ou representante de outro objecto,
para controlar o acesso a este mesmo objecto.
A Proxy um intermedirio entre um cliente C e um objecto O, que
implementa a mesma interface de O e adiciona outros controles e/ou
optimizaes necessrias. O proxy deve representar o objecto da
forma o mais transparente possvel. De preferncia de modo a que o
cliente no saiba que est interagir com um representante em vez do
objecto original.
Um exemplo so as proxies utilizados para persistncia. Supondo que
se tem um objecto que possui para alm da propriedade nome,
outras propriedades que tm de se obter de uma base de dados
(campos blob, memo, text, etc.). Supondo, tambm, que se pretende
obter 10.000 instncias para apresentar uma tabela ao utilizador.
No necessrio obter logo as propriedades complexas, bastando
criar uma proxy que obtenha apenas o nome e evoque o objecto real
(obtendo as propriedades mais complexas) apenas nas situaes em
que so realmente necessrias.
Participantes:
As classes e/ou objectos que participam no padro so:
Proxy
o Mantm a referncia que permite proxy aceder ao
objecto real. A Proxy pode-se referir ao Subject se as
interfaces de RealSubject e Subject forem as mesmas.
o Fornece uma interface idntica a Subject para que a
proxy possa ser substituda pelo objecto real.
o Controla o acesso ao objecto real podendo ser
responsvel pela sua criao e remoo.
o Outras responsabilidades dependem do tipo de proxy:
Proxies remotas so responsveis por codificar o
pedido e os seus argumentos, e envi-lo codificado
ao objecto real, num diferente espao de endereo.
Proxies virtuais podem fazer cache de informao
adicional acerca do objecto real, para que se possa
adiar o acesso ao mesmo.
Proxies de proteco verificam se quem a evoca
tem privilgios de acesso necessrios para efectuar
o pedido.
Subject
Anacleto Correia
59
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
60
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro Proxy
// aplicao Cliente
public class PatProxy {
public static void main(String[] args) {
// Cria proxy math
IMath p = new MathProxy();
// Fazer os clculos
System.out.println("4
System.out.println("4
System.out.println("4
System.out.println("4
+
*
/
2
2
2
2
=
=
=
=
"
"
"
"
+
+
+
+
p.adicionar(4, 2));
p.subtrair(4, 2));
p.multiplicar(4, 2));
p.dividir(4, 2));
}
}
// "Subject"
interface IMath {
double adicionar(double x, double y);
double subtrair(double x, double y);
double multiplicar(double x, double y);
double dividir(double x, double y);
}
// "RealSubject"
class Math
implements IMath {
public double adicionar(double x, double y) {
return x + y;
}
public double subtrair(double x, double y) {
Anacleto Correia
61
IPS-ESTSetbal
Padres de Desenho
return x - y;
}
public double multiplicar(double x, double y) {
return x * y;
}
public double dividir(double x, double y) {
return x / y;
}
}
// "Objecto Proxy "
class MathProxy
implements IMath {
Math math;
public MathProxy() {
math = new Math();
}
public double adicionar(double x, double y) {
return (x+y);
}
public double subtrair(double x, double y) {
return (x-y);
}
public double multiplicar(double x, double y) {
// implementada custa de RealSubject
return math.multiplicar(x, y);
}
public double dividir(double x, double y) {
// implementada custa de RealSubject
return math.dividir(x, y);
}
}
/*
4 + 2 = 6.0
4 - 2 = 2.0
4 * 2 = 8.0
4 / 2 = 2.0
*/
Anacleto Correia
62
IPS-ESTSetbal
Padres de Desenho
Padres de Comportamento
Padres que caracterizam formas de interaco entre classes e
objectos.
Handler
o Define uma interface para tratar os pedidos
o (opcional) implementa a ligao ao sucessor
ConcreteHandler
o Trata os pedidos pelos quais responsvel
o Pode aceder ao seu sucessor
o Se o ConcreteHandler pode tratar o pedido, trata-o; caso
contrrio envia-o ao seu sucessor
Client
o Inicia o pedido a um objecto ConcreteHandler na cadeia
Anacleto Correia
63
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro Chain of Responsibility
// aplicao Cliente
public class PatChResp {
public static void main(String[] args) {
// Definir a Cadeia de Responsabilidades
Aprovador pedro = new Director("Pedro");
Aprovador afonso = new VicePresidente("Afonso");
Aprovador maria = new Presidente("Maria");
pedro.setSucessor(afonso);
afonso.setSucessor(maria);
// Gera e processa os pedidos de compra
Compra p = new Compra(2034, 350.00, "Para Stock");
pedro.processaPedido(p);
p = new Compra(2035, 32590.10, "Projecto X");
pedro.processaPedido(p);
p = new Compra(2036, 122100.00, "Projecto Y");
pedro.processaPedido(p);
}
}
Anacleto Correia
64
IPS-ESTSetbal
Padres de Desenho
// "Handler"
abstract class Aprovador {
private String nome;
protected Aprovador sucessor;
public Aprovador(String nome) {
this.nome = nome;
}
public void setSucessor(Aprovador sucessor) {
this.sucessor = sucessor;
}
public String getNome() {
return nome;
}
public abstract void processaPedido(Compra compra);
}
// "ConcreteHandler"
class Director
extends Aprovador {
public Director(String nome) {
super(nome);
}
public void processaPedido(Compra compra) {
if (compra.getValor() < 10000.0) {
System.out.println(this.getClass().getName() + " " + this.getNome()
+ " aprovou pedido n" +
compra.getNumero());
}
else if (sucessor != null) {
sucessor.processaPedido(compra);
}
}
}
// "ConcreteHandler"
class VicePresidente
extends Aprovador {
public VicePresidente(String nome) {
super(nome);
}
public void processaPedido(Compra compra) {
if (compra.getValor() < 25000.0) {
System.out.println(this.getClass().getName() + " " + this.getNome() +
" aprovou pedido n" +
compra.getNumero());
}
else if (sucessor != null) {
sucessor.processaPedido(compra);
}
}
}
// "ConcreteHandler"
class Presidente
extends Aprovador {
public Presidente(String nome) {
super(nome);
}
public void processaPedido(Compra compra) {
if (compra.getValor() < 100000.0) {
System.out.println(this.getClass().getName() + " " + this.getNome() +
" aprovou pedido n" +
compra.getNumero());
}
else {
System.out.println(
"Pedido n" + compra.getNumero() +
" requer uma reunio com o Presidente!");
}
}
Anacleto Correia
65
IPS-ESTSetbal
Padres de Desenho
}
// Detalhe do Pedido
class Compra {
private int numero;
private double valor;
private String finalidade;
// Construtor
public Compra(int numero, double valor, String finalidade) {
this.numero = numero;
this.valor = valor;
this.finalidade = finalidade;
}
// Propriedades
public double getValor() {
return valor;
}
public void setValor(double valor) {
this.valor = valor;
}
public String getFinalidade() {
return finalidade;
}
public void setFinalidade(String finalidade) {
this.finalidade = finalidade;
}
int getNumero() {
return numero;
}
public void setNumero(int numero) {
this.numero = numero;
}
}
/*
Director Pedro aprovou pedido n2034
Presidente Maria aprovou pedido n2035
Pedido n2036 requer uma reunio com o Presidente!
*/
Anacleto Correia
66
IPS-ESTSetbal
Padres de Desenho
Command (Comando)
O padro Command encapsula um pedido num objecto, permitindo:
parametrizar clientes com pedidos diferentes, enfileirar pedidos, fazer
log de pedidos e dar suporte a operaes de undo.
Por outras palavras, quando se pretender realizar uma aco X, em
vez de evocar o mtodo executarX() de uma classe enviando-lhe
parmetros, cria-se o objecto AccaoX e configura-se as suas
propriedades com os valores dos parmetros daquele comando.
Este padro a base do Xwork. No Xwork configura-se as aces
(comandos) s quais o sistema ir responder e a classe que
implementa o comando. Quando se acede a determinada aco,
automaticamente: criada uma nova instncia da classe da aco;
atribudos os parmetros que foram enviados; executada a aco; e
retornado um valor como resultado.
Participantes:
As classes e/ou objectos que participam no padro so:
Command
o Declara uma interface para execuo de uma operao
ConcreteCommand
o Define uma ligao entre o objecto Receiver e uma aco
o Implementa o mtodo Execute, evocando as
correspondentes operaes no Receiver
Client
o Cria um objecto ConcreteCommand e estabelece o seu
receptor
Invoker
o Pede ao comando para tomar conta do pedido
Receiver
o Sabe como executar as operaes associadas realizao
do pedido.
Anacleto Correia
67
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro Command: transforma um pedido num objecto
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
// Command
interface Command {
void executar();
}
// Receiver
// Sabe como executar as operaes associadas a um pedido.
// Qualquer classe pode actuar como Receiver.
Anacleto Correia
68
IPS-ESTSetbal
Padres de Desenho
class ReceptorOla {
public void action() {
System.out.print("\nSou o Receiver de Ola!");
}
}
// Receiver
class ReceptorMundo {
public void faz() {
System.out.print("\nSou o Receiver de Mundo!");
}
}
// Receiver
class ReceptorEuSou {
public void diz() {
System.out.print("\nSou o Receiver de EuSou!");
}
}
// ConcreteCommand
//Define a ligao entre uma aco e o objecto receptor
//Invoca as operaes correspondentes no receptor
class Ola
implements Command {
ReceptorOla r;
public Ola(ReceptorOla r) {
this.r = r;
}
public void executar() {
r.action();
}
}
// ConcreteCommand
class Mundo
implements Command {
ReceptorMundo r;
public Mundo(ReceptorMundo r) {
this.r = r;
}
public void executar() {
r.faz();
}
}
// ConcreteCommand
class EuSou
implements Command {
ReceptorEuSou r;
public EuSou(ReceptorEuSou r) {
this.r = r;
}
public void executar() {
r.diz();
}
}
// Invoker
// Pede a Command para tratar o seu pedido
class Macro {
private List pedidos = new ArrayList();
Anacleto Correia
69
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
70
IPS-ESTSetbal
Padres de Desenho
Interpreter (Interpretador)
Dada uma linguagem, define uma representao da sua gramtica e
um interpretador que utiliza a representao da gramtica para
interpretar frases dessa linguagem.
Interpreter consiste pois em criar uma linguagem de representao
de operaes, construir um interpretador para essa linguagem e
permitir que sejam enviados comandos escritos na linguagem
especificada, que sero transformados em operaes. Apesar de ser
uma soluo mais complexa, pois envolve a criao de um
interpretador de comandos, d maior flexibilidade ao utilizador, que
pode alterar as funcionalidades do sistema atravs da linguagem de
comandos, sem precisar de recompilar as classes.
Participantes:
As classes e/ou objectos que participam no padro so:
AbstractExpression
o Declara uma interface para execuo de um mtodo.
TerminalExpression
o Implementa o mtodo Interpret associado com smbolos
terminais da gramtica.
o necessria uma instncia para cada smbolo terminal na
frase.
NonterminalExpression
o necessria uma destas classes para cada regra R ::=
R1R2...Rn da gramtica.
o Mantm variveis de instncia do tipo AbstractExpression
para cada um dos smbolos R1 a Rn.
o Implementa o mtodo Interpret para smbolos no
terminais na gramtica. Interpret tipicamente evoca-se a
si prprio recursivamente nas variveis representando R1
a Rn.
Context
o Contm informao que global ao Interpreter.
Client
o Constri (ou dada) uma rvore de sintaxe abstracta
representando uma frase particular na linguagem que a
gramtica define. A rvore de sintaxe abstracta
montada de instncias das classes NonterminalExpression
e TerminalExpression.
o Evoca o mtodo Interpret.
Anacleto Correia
71
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
72
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro Interpret
import java.util.ArrayList;
// aplicao Cliente
public class PatInterp {
public static void main(String[] args) {
String romano = "MCMXXVIII";
Contexto contexto = new Contexto(romano);
// Construir a 'parse tree'
ArrayList arvore = new ArrayList();
arvore.add(new ExpressaoMilhares());
arvore.add(new ExpressaoCentenas());
arvore.add(new ExpressaoDezenas());
arvore.add(new ExpressaoUnidades());
// Interpret
for (int i=0;i<arvore.size();i++ )
{
Expressao exp= (Expressao) arvore.get(i);
exp.interpretar(contexto);
}
System.out.println(romano + " = " + contexto.getOutput());
}
}
// "Context"
class Contexto
{
private String input;
private int output;
// Construtor
public Contexto(String input)
{
this.input = input;
}
// Propriedades
public String getInput() {
return input;
}
public void setInput(String value) {
input = value;
}
public int getOutput() {
return output;
}
public void setOutput(int value) {
output = value;
}
}
// "AbstractExpression"
abstract class Expressao
{
public void interpretar(Contexto contexto)
{
if (contexto.getInput().length() == 0)
return;
if (contexto.getInput().startsWith(nove()))
{
contexto.setOutput( contexto.getOutput()+ (9 * multiplicador()));
contexto.setInput( contexto.getInput().substring(2));
}
else if (contexto.getInput().startsWith(quatro()))
{
contexto.setOutput(contexto.getOutput()+ (4 * multiplicador()));
contexto.setInput( contexto.getInput().substring(2));
}
else if (contexto.getInput().startsWith(cinco()))
{
contexto.setOutput(contexto.getOutput()+ (5 * multiplicador()));
contexto.setInput( contexto.getInput().substring(1));
}
while (contexto.getInput().startsWith(um()))
Anacleto Correia
73
IPS-ESTSetbal
Padres de Desenho
{
contexto.setOutput(contexto.getOutput()+ (1 * multiplicador()));
contexto.setInput( contexto.getInput().substring(1));
}
}
public
public
public
public
public
abstract
abstract
abstract
abstract
abstract
String um();
String quatro();
String cinco();
String nove();
int multiplicador();
}
// Verificao dos Milhares para o numero romano M
// "TerminalExpression"
class ExpressaoMilhares extends Expressao
{
public String um() { return "M"; }
public String quatro(){ return " "; }
public String cinco(){ return " "; }
public String nove(){ return " "; }
public int multiplicador() { return 1000; }
}
// Verificao das centenas C, CD, D or CM
// "TerminalExpression"
class ExpressaoCentenas extends Expressao
{
public String um() { return "C"; }
public String quatro(){ return "CD"; }
public String cinco(){ return "D"; }
public String nove(){ return "CM"; }
public int multiplicador() { return 100; }
}
// Verificao das dezenas para X, XL, L and XC
// "TerminalExpression"
class ExpressaoDezenas extends Expressao
{
public String um() { return "X"; }
public String quatro(){ return "XL"; }
public String cinco(){ return "L"; }
public String nove(){ return "XC"; }
public int multiplicador() { return 10; }
}
// Verificao das unidades para I, II, III, IV, V, VI, VI, VII, VIII, IX
// "TerminalExpression"
class ExpressaoUnidades extends Expressao
{
public String um() { return "I"; }
public String quatro(){ return "IV"; }
public String cinco(){ return "V"; }
public String nove(){ return "IX"; }
public int multiplicador() { return 1; }
}
/*
MCMXXVIII = 1928
*/
Anacleto Correia
74
IPS-ESTSetbal
Padres de Desenho
Iterator (Iterador)
Fornece um meio de aceder aos elementos de uma coleco de
objectos, de forma sequencial e sem expor sua representao
interna. A interface java.util.Iterator um exemplo do padro
Iterator.
Participantes:
As classes e/ou objectos que participam no padro so:
Iterator
o Define uma interface para acesso sequencial aos
elementos de uma estrutura ou agregado.
ConcreteIterator
o Implementa a interface Iterator.
o Mantm registo da posio corrente durante a passagem
pelo agregado de elementos.
Aggregate
o Define uma interface para criao do objecto Iterator.
ConcreteAggregate
o Implementa a criao da interface Iterator para retornar
uma instncia de ConcreteIterator.
75
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro Iterator
// Iterator
interface Iterator {
boolean hasNext();
Object next();
}
// Agregate
interface Pilha {
//Mtodos selectores
public int tamanho();
public boolean estaVazia();
public Object topo();
//Mtodos de actualizao
public void empilha(Object elemento);
public Object desempilha();
}
// ConcreteAggregate
class PilhaArray
implements Pilha {
// ConcreteIterator
private class PilhaArrayIterator
implements Iterator {
int pos = -1;
public boolean hasNext() {
return (pos < topo);
}
Anacleto Correia
76
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
77
IPS-ESTSetbal
Padres de Desenho
while (ai.hasNext()) {
System.out.println("\n1 Iterador: " + ai.next());
System.out.print(" 2 Iterador:");
for (ai2 = s.getIterator(); ai2.hasNext(); )
System.out.print(" " + ai2.next());
}
}
}
/*
1 Iterador: 0
2 Iterador: 0
1 Iterador: 1
2 Iterador: 0
1 Iterador: 2
2 Iterador: 0
1 Iterador: 3
2 Iterador: 0
1 Iterador: 4
2 Iterador: 0
*/
Anacleto Correia
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
78
IPS-ESTSetbal
Padres de Desenho
Mediator (Mediador)
Define um objecto que encapsula a forma como um conjunto de
objectos interage. O padro Mediator promove uma relao fraca
entre objectos evitando que se referenciem explicitamente uns aos
outros, permitindo assim, que suas interaces variem
independentemente.
Quando diversos objectos precisam de interagir entre si, cria-se
geralmente uma associao entre eles, o que nem sempre
desejado. Para diminuir o acoplamento desta associao, pode-se
criar uma classe mediadora, que encapsula a comunicao entre os
objectos. O mediador conhece todos mas estes apenas conhecem o
mediador.
Participantes:
As classes e/ou objectos que participam no padro so:
Mediator
o Define uma interface para comunicao com objectos
Colleague
ConcreteMediator
o Implementa comportamento cooperativo coordenando
objectos Colleague
o Conhece e mantm os objectos ConcreteColleague
ConcreteColleague
o Cada classe ConcreteColleague conhece o seu objecto
Mediator
o Cada colega comunica com o mediator, quando de outra
forma comunicaria com outro objecto ConcreteColleague
Anacleto Correia
79
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro Mediator
import java.util.HashMap;
// Aplicao Cliente
public class PatMediator {
public static void main(String[] args) {
// Criao de sala de conversao
SalaConversacao salaConversacao = new SalaConversacao();
// Criao e
Participante
Participante
Participante
Participante
Participante
registo de participantes
George = new Beatle("George");
Paul = new Beatle("Paul");
Ringo = new Beatle("Ringo");
John = new Beatle("John");
Yoko = new NaoBeatle("Yoko");
salaConversacao.registar(George);
salaConversacao.registar(Paul);
salaConversacao.registar(Ringo);
salaConversacao.registar(John);
salaConversacao.registar(Yoko);
// participantes na conversa
Yoko.enviar("John", "Hi John!");
Paul.enviar("Ringo", "All you need is love");
Ringo.enviar("George", "My sweet Lord");
Paul.enviar("John", "Can't buy me love");
John.enviar("Yoko", "My sweet love");
}
}
// "Mediator"
abstract class AbstractChatroom {
public abstract void registar(Participante participante);
public abstract void enviar(
String de, String para, String mensagem);
}
// "ConcreteMediator"
class SalaConversacao
extends AbstractChatroom {
private HashMap participantes = new HashMap();
Anacleto Correia
80
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
81
IPS-ESTSetbal
Padres de Desenho
}
}
/*
Para
Para
Para
Para
Para
*/
um
um
um
um
um
Anacleto Correia
82
IPS-ESTSetbal
Padres de Desenho
Memento (Memria)
Sem violar o princpio de encapsulamento, captura e externaliza o
estado interno de um objecto de forma a poder restaurar mais tarde
esse estado do objecto.
Memento o padro utilizado para operaes de desfazer (tambm
conhecida como undo ou Ctrl+Z). Consiste em guardar snapshots
(fotografias) de determinados estados de objectos para que possam
ser posteriormente restaurados, caso necessrio. Num programa de
desenho, por exemplo, guardaramos (em objectos, ficheiros, strings,
) a posio, tamanho, cor e formato dos objectos que compem o
desenho medida que o utilizador for desenhando. Caso se
pretendesse retornar a um momento anterior do desenho, bastaria
restaurar uma das fotografias armazenadas.
Participantes:
As classes e/ou objectos que participam no padro so:
Memento
o Armazena o estado interno do objecto Originator. O
Memento pode armazenar mais ou menos do contedo do
estado interno de Originator, em funo do critrio deste.
o Protege contra o acesso de outros objectos que no o
Originator. Memento tem de facto duas interfaces.
Caretaker v a interface mais estreita de Memento
apenas pode passar o Memento para outros objectos.
Originator, pelo contrrio, v uma interface mais
alargada, que lhe permite acesso a todos os dados
necessrios para se restaurar o seu estado prvio.
Idealmente, apenas ao Originator, que produz o
Memento, ser permitido o acesso ao estado interno
deste.
Originator
o Cria um Memento contendo um snapshot do seu estado
corrente.
o Utiliza o Memento para restaurar o seu estado interno.
Caretaker
o responsvel pela salvaguarda de Memento.
o Nunca opera sobre ou examina o contedo de Memento.
Anacleto Correia
83
IPS-ESTSetbal
Padres de Desenho
Este padro comum nas situaes em que por exemplo se faz uma
auto-reparao. Imagine-se a reparao dos traves de cilindro, de
numa viatura. Os cilindros so removidos de ambos os lados,
expondo os traves do lado direito e esquerdo. S se desmonta um
dos lados, enquanto o outro serve de auxiliar de memria (Memento)
da forma como o travo deve ficar montados. S aps um dos lados
ter sido reparado, que o outro desmontado. O travo reparado
ser ento Memento do segundo a ser reparado.
Exemplo
// padro Memento
// Cliente
public class PatMemento {
public static void main(String[] args) {
PrevisaoVendas s = new PrevisaoVendas();
s.setNome("Joo Pedro");
s.setTelefone ("21-5630990");
s.setOrcamento(25000.0);
// Armazena o estado interno
ArmazenaMemoria m = new ArmazenaMemoria();
m.setMemento(s.GuardarMemento());
// Continua a alterar o originator
s.setNome("Afonso Silva");
s.setTelefone("22-2097111");
s.setOrcamento(1000000.0);
Anacleto Correia
84
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
85
IPS-ESTSetbal
Padres de Desenho
this.nome = nome;
this.telefone = telefone;
this.orcamento = orcamento;
}
// Propriedades
public String getNome() {
return nome;
}
public void setNome(String valor) {
nome = valor;
}
public String getTelefone() {
return telefone;
}
public void setTelefone(String valor) {
telefone = valor;
}
public double getOrcamento() {
return orcamento;
}
public void setOrcamento(double valor) {
orcamento = valor;
}
}
// "Caretaker"
class ArmazenaMemoria
{
private Memento memento;
// Propriedade
public Memento getMemento() {
return memento;
}
public void setMemento(Memento valor) {
memento = valor;
}
}
/*
Nome: Joo Pedro
Telefone: 21-5630990
Orcamento: 25000.0
Guardar estado -Nome: Afonso Silva
Telefone: 22-2097111
Orcamento: 1000000.0
Recuperar estado -Nome: Joo Pedro
Telefone: 21-5630990
Orcamento: 25000.0
*/
Anacleto Correia
86
IPS-ESTSetbal
Padres de Desenho
Observer (Observador)
Define uma dependncia um-para-muitos entre objectos, de forma a
avisar vrios objectos (observadores), quando o estado de um outro
objecto (observado) se altera. Os objectos observadores podem
assim, desencadear as aces necessrias actualizao do seu
estado.
O padro observador til, principalmente quando se utiliza a
abordagem MVC (Model-View-Controller) no desenvolvimento. Os
objectos de domnio so a camada de modelo, enquanto que as
interfaces grficas formam a camada de viso. Quando vrios
componentes grficos mostram dados de um determinado objecto do
modelo e este alterado, o que fazer para que todos os componentes
grficos se actualizem automaticamente? O padro Observer resolve
isso fazendo com que o objecto do modelo seja o observado e as
interfaces grficas sejam os observadores. Quando criado, cada
observador regista-se junto do observado, que mantm uma lista de
observadores na sua estrutura interna. Assim, quando o observado
alterado, envia uma mensagem para cada observador, informando-o
do ocorrido. Este ento pode-se actualizar em conformidade.
Este padro reduz o acoplamento entre os objectos, pois na
abordagem MVC, no razovel que o objecto do modelo conhea
cada uma das interfaces que o manipula. Existe suporte para este
padro na API J2SE: java.util.Observer e java.util.Observable.
Participantes:
As classes e/ou objectos que participam no padro so:
Subject
o Conhece os seus observadores. Qualquer nmero de
objectos Observer pode observar um Subject.
o Fornece uma interface para adicionar e remover objectos
Observer.
ConcreteSubject
o Armazena os estados que interessam ao
ConcreteObserver.
o Envia uma notificao aos Observers, quando o estado se
altera.
Observer
o Define uma interface de alterao, para os objectos que
devam ser notificados de alteraes verificados no
Subject.
Anacleto Correia
87
IPS-ESTSetbal
Padres de Desenho
ConcreteObserver
o Mantm uma referncia para o objecto ConcreteSubject.
o Armazena o estado consistente com o de Subject.
o Implementa a interface de actualizao definida em
Observer, para que o seu estado seja consistente com o
de Subject.
Anacleto Correia
88
IPS-ESTSetbal
Padres de Desenho
Exemplo
//
//
//
//
Padro Observer
Definir dependncias entre objectos do tipo um-para-muitos.
Quando o objecto altera o seu estado, todos os objectos
dependentes so notificados para poderem agir em conformidade.
// Subject
import java.util.Observable;
// Observer
import java.util.Observer;
class Flor {
private boolean estaAberto;
private NotificadorAbertura notificaAbertura = new NotificadorAbertura();
private NotificadorFecho notificaFecho = new NotificadorFecho();
public Flor() {
estaAberto = false;
}
public void abre() { // Abre as ptalas
estaAberto = true;
notificaAbertura.notifyObservers();
notificaFecho.abre();
}
public void fecha() { // Fecha as ptalas
estaAberto = false;
notificaFecho.notifyObservers();
notificaAbertura.fecha();
}
public Observable notificadorAbertura() {
return notificaAbertura;
}
public Observable notificadorFecho() {
return notificaFecho;
}
// ConcreteSubject
private class NotificadorAbertura
extends Observable {
private boolean jaAberto = false;
public void notifyObservers() {
if (estaAberto && !jaAberto) {
setChanged();
super.notifyObservers();
jaAberto = true;
}
}
public void fecha() {
jaAberto = false;
}
}
// ConcreteSubject
private class NotificadorFecho
extends Observable {
private boolean jaFechado = false;
public void notifyObservers() {
if (!estaAberto && !jaFechado) {
setChanged();
super.notifyObservers();
jaFechado = true;
}
}
public void abre() {
jaFechado = false;
}
}
}
Anacleto Correia
89
IPS-ESTSetbal
Padres de Desenho
class Abelha {
private String nome;
private ObservadorAbertura abreObsrv = new ObservadorAbertura();
private ObservadorFecho fechaObsrv = new ObservadorFecho();
public Abelha(String nm) {
nome = nm;
}
// ConcreteObserver
private class ObservadorAbertura
implements Observer { // observa aberturas
public void update(Observable ob, Object a) {
System.out.println("Abelha " + nome + ": hora do pequeno-almoo!");
}
}
// ConcreteObserver
private class ObservadorFecho
implements Observer { // observa fechos
public void update(Observable ob, Object a) {
System.out.println("Abelha " + nome + ": hora de deitar!");
}
}
public Observer observadorAbertura() {
return abreObsrv;
}
public Observer observadorFecho() {
return fechaObsrv;
}
}
class BeijaFlor {
private String nome;
private ObservadorAbertura abreObsrv = new ObservadorAbertura();
private ObservadorFecho fechaObsrv = new ObservadorFecho();
public BeijaFlor(String nm) {
nome = nm;
}
// ConcreteObserver
private class ObservadorAbertura
implements Observer { // obs abertu
public void update(Observable ob, Object a) {
System.out.println("BeijaFlor " + nome + ": hora do pequeno-almoo!");
}
}
// ConcreteObserver
private class ObservadorFecho
implements Observer { // observa fechos
public void update(Observable ob, Object a) {
System.out.println("BeijaFlor " + nome + ": hora de deitar!");
}
}
public Observer observadorAbertura() {
return abreObsrv;
}
public Observer observadorFecho() {
return fechaObsrv;
}
}
// Cliente
public class ObserverPattern {
public static void main(String args[]) {
Flor f = new Flor(); // objecto Observado
Abelha aA = new Abelha("A"); // objecto Observador
Abelha aB = new Abelha("B"); // objecto Observador
BeijaFlor bA = new BeijaFlor("A"); // objecto Observador
BeijaFlor bB = new BeijaFlor("B"); // objecto Observador
System.out.println("=> Adiciona Observadores");
f.notificadorAbertura().addObserver(bA.observadorAbertura());
Anacleto Correia
90
IPS-ESTSetbal
Padres de Desenho
f.notificadorAbertura().addObserver(bB.observadorAbertura());
f.notificadorAbertura().addObserver(aA.observadorAbertura());
f.notificadorAbertura().addObserver(aB.observadorAbertura());
f.notificadorFecho().addObserver(bA.observadorFecho());
f.notificadorFecho().addObserver(bB.observadorFecho());
f.notificadorFecho().addObserver(aA.observadorFecho());
f.notificadorFecho().addObserver(aB.observadorFecho());
// BeijaFlor B decide adormecer
System.out.println("=> BeijaFlor B decide adormecer");
f.notificadorAbertura().deleteObserver(bB.observadorAbertura());
System.out.println("=> Flor abre");
f.abre(); // Uma alterao que interessa aos observadores
f.abre(); // J estava aberta
// BeijaFlor A no quer ir para a cama
System.out.println("=> BeijaFlor A no quer ir para a cama");
f.notificadorFecho().deleteObserver(bA.observadorFecho());
System.out.println("=> Flor fecha");
f.fecha();
f.fecha(); // J estava fechada
System.out.println("=> Remove Observadores Abertura");
f.notificadorAbertura().deleteObservers(); // Levantam-se mais tarde
System.out.println("=> Flor abre");
f.abre();
System.out.println("=> Flor fecha");
f.fecha();
}
}
/*
=> Adiciona Observadores
=> BeijaFlor B decide adormecer
=> Flor abre
Abelha B: hora do pequeno-almoo!
Abelha A: hora do pequeno-almoo!
BeijaFlor A: hora do pequeno-almoo!
=> BeijaFlor A no quer ir para a cama
=> Flor fecha
Abelha B: hora de deitar!
Abelha A: hora de deitar!
BeijaFlor B: hora de deitar!
=> Remove Observadores Abertura
=> Flor abre
=> Flor fecha
Abelha B: hora de deitar!
Abelha A: hora de deitar!
BeijaFlor B: hora de deitar!
*/
Anacleto Correia
91
IPS-ESTSetbal
Padres de Desenho
State (Estado)
Permite que um objecto altere seu comportamento quando o seu
estado interno muda. O objecto aparenta mudar de classe com a
mudana de estado.
Este padro visa especificar diferentes estados que um objecto pode
assumir. Ao executar um determinado mtodo, verificado em que
estado o objecto se encontra, podendo-se realizar uma operao
diferente para cada estado.
Participantes:
As classes e/ou objectos que participam no padro so:
Context
o Define uma interface para os clientes.
o Mantm uma instncia de uma subclasse ConcreteState
que define o estado actual.
State
o Define uma interface para encapsular o comportamento
associado a um estado particular de Context.
Concrete State
o Cada subclasse implementa o comportamento associado a
um estado particular de Context.
Anacleto Correia
92
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
93
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro State
// Aplicao Cliente
public class PatState {
public static void main(String[] args) {
// Abrir nova Conta
Conta conta = new Conta("Jim Johnson");
// Efectuar transaces financeiras
conta.deposito(500.0);
conta.deposito(300.0);
conta.deposito(550.0);
conta.pagarJuro();
conta.levantar(2000.00);
conta.levantar(1100.00);
}
}
// "State"
abstract class Estado {
protected Conta conta;
protected double saldo;
protected double juro;
protected double limiteInferior;
protected double limiteSuperior;
// Propriedades
public Conta getConta() {
return conta;
}
public void setConta(Conta valor) {
conta = valor;
}
public double getSaldo() {
return saldo;
}
public void setSaldo(double valor) {
saldo = valor;
}
public abstract void deposito(double quantia);
public abstract void levantar(double quantia);
public abstract void pagarJuro();
}
// "ConcreteState"
// Conta a descoberto
class EstadoVermelho
extends Estado {
double taxaServico;
// Construtor
public EstadoVermelho(Estado estado) {
this.saldo = estado.getSaldo();
this.conta = estado.getConta();
inicializar();
}
private void inicializar() {
// Estes valores devem vir de uma base de dados
juro = 0.0;
limiteInferior = -100.0;
limiteSuperior = 0.0;
taxaServico = 15.00;
}
public void deposito(double quantia) {
saldo += quantia;
Anacleto Correia
94
IPS-ESTSetbal
Padres de Desenho
verificarAlteracaoEstado();
}
public void levantar(double quantia) {
saldo = saldo - taxaServico;
System.out.println("No existem fundos disponveis para levantamento!");
}
public void pagarJuro() {
// No pago juro
}
private void verificarAlteracaoEstado() {
if (saldo > limiteSuperior) {
conta.setEstado(new EstadoPrata(this));
}
}
}
// "ConcreteState"
// Silver um estado em que no h juros de depsito
class EstadoPrata
extends Estado {
// construtores sobrecarregados
public EstadoPrata(Estado estado) {
this(estado.getSaldo(), estado.getConta());
}
public EstadoPrata(double saldo, Conta conta) {
this.saldo = saldo;
this.conta = conta;
inicializar();
}
private void inicializar() {
// Estes valores devem vir de uma base de dados
juro = 0.0;
limiteInferior = 0.0;
limiteSuperior = 1000.0;
}
public void deposito(double quantia) {
saldo += quantia;
verificarAlteracaoEstado();
}
public void levantar(double quantia) {
saldo -= quantia;
verificarAlteracaoEstado();
}
public void pagarJuro() {
saldo += juro * saldo;
verificarAlteracaoEstado();
}
private void verificarAlteracaoEstado() {
if (saldo < limiteInferior) {
conta.setEstado(new EstadoVermelho(this));
}
else if (saldo > limiteSuperior) {
conta.setEstado(new EstadoOuro(this));
}
}
}
// "ConcreteState"
// Estado em que h juro de depsitos
class EstadoOuro
extends Estado {
// construtores sobrecarregados
public EstadoOuro(Estado estado) {
this(estado.getSaldo(), estado.getConta());
}
public EstadoOuro(double saldo, Conta conta) {
this.saldo = saldo;
Anacleto Correia
95
IPS-ESTSetbal
Padres de Desenho
this.conta = conta;
inicializar();
}
private void inicializar() {
// Estes valores devem vir de uma base de dados
juro = 0.05;
limiteInferior = 1000.0;
limiteSuperior = 10000000.0;
}
public void deposito(double quantia) {
saldo += quantia;
verificarAlteracaoEstado();
}
public void levantar(double quantia) {
saldo -= quantia;
verificarAlteracaoEstado();
}
public void pagarJuro() {
saldo += juro * saldo;
verificarAlteracaoEstado();
}
private void verificarAlteracaoEstado() {
if (saldo < 0.0) {
conta.setEstado(new EstadoVermelho(this));
}
else if (saldo < limiteInferior) {
conta.setEstado(new EstadoPrata(this));
}
}
}
// "Context"
class Conta {
private Estado estado;
private String owner;
// Construtor
public Conta(String owner) {
// As novas contas so por omisso 'Silver'
this.owner = owner;
estado = new EstadoPrata(0.0, this);
}
// Propriedades
public double getSaldo() {
return estado.getSaldo();
}
public Estado getEstado() {
return estado;
}
public void setEstado(Estado valor) {
estado = valor;
}
public void deposito(double quantia) {
estado.deposito(quantia);
System.out.println("Depsito --- " + quantia);
System.out.println(" Saldo = " + this.getSaldo());
System.out.println(" Estado = " +
this.getEstado().getClass().getName());
System.out.println("");
}
public void levantar(double quantia) {
estado.levantar(quantia);
System.out.println("Levantamento --- " + quantia);
System.out.println(" Saldo = " + this.getSaldo());
System.out.println(" Estado = " +
this.getEstado().getClass().getName());
}
Anacleto Correia
96
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
97
IPS-ESTSetbal
Padres de Desenho
Strategy (Estratgia)
Define uma famlia de algoritmos, que podem ser utilizados de forma
intermutvel. O padro Strategy permite que o algoritmo varie
independentemente dos clientes que o usam. Cada algoritmo
encapsulado numa classe.
Strategy idntico a State na sua implementao. A diferena que
uma estratgia no se altera, enquanto o estado pode variar
substancialmente. Isso naturalmente relativo, e poderamos
considerar que ambos os padres so, de facto, um s. No entanto
por vezes pretende-se representar um estado, enquanto que noutras,
pretende-se representar um algoritmo.
Participantes:
As classes e/ou objectos que participam no padro so:
Strategy
o Declara uma interface comum a todos os algoritmos
suportados. Context utiliza esta interface para evocar o
algoritmo definido por um ConcreteStrategy
ConcreteStrategy
o Implementa o algoritmo utilizando a interface Strategy.
Context
o configurado com um objecto ConcreteStrategy.
o Mantm uma referncia para um objecto Strategy.
o Pode definir uma interface para permitir o acesso de
Strategy aos seus dados.
Anacleto Correia
98
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro Strategy
// Strategy
interface Preco {
double algoritmo(double p);
}
// As diferentes estratgias
class PrecoPublico implements Preco {
public double algoritmo(double p) {
return p;
}
}
class PrecoCredito implements Preco {
public double algoritmo(double p) {
return (p*1.2);
}
}
class PrecoVip implements Preco {
public double algoritmo(double p) {
return (p*0.8);
}
}
// O "Context" controla a estratgia
class DeterminaPreco {
private Preco politicaPreco;
public DeterminaPreco(Preco estrat) {
politicaPreco = estrat;
}
double precoAplicavel(double p) {
return politicaPreco.algoritmo(p);
}
void trocaAlgoritmo(Preco novoAlgoritmo) {
politicaPreco = novoAlgoritmo;
Anacleto Correia
99
IPS-ESTSetbal
Padres de Desenho
}
}
// A classe Cliente
public class testaPadrao {
static DeterminaPreco dt =new DeterminaPreco(new
PrecoPublico());
static double preco = 40.0;
public static void print(double p) {
System.out.println(p);
}
public static void main(String args[]) {
print(dt.precoAplicavel(preco));
dt.trocaAlgoritmo(new PrecoVip());
print(dt.precoAplicavel(preco));
}
}
/*
40.0
32.0
*/
Anacleto Correia
100
IPS-ESTSetbal
Padres de Desenho
AbstractClass
o Define mtodos abstractos, que as subclasses concretas
iro definir, para implementar passos concretos do
algoritmo.
o Implementa um mtodo-padro, que define o esqueleto
de um algoritmo. O mtodo-padro evoca os mtodos
abstractos ou outros mtodos definidos na classe
AbstractClass, ou mtodos definidos noutros objectos.
ConcreteClass
o Implementa os mtodos abstractos definidos na classe
AbstractClass, de forma que a subclasse possa realizar
passos especializados do algoritmo.
Anacleto Correia
101
IPS-ESTSetbal
Padres de Desenho
Exemplo
Padro Template Method
// AbstractClass
abstract class ClasseAbstracta {
public ClasseAbstracta() { template(); }
abstract void customiza1();
abstract void customiza2();
private void template() {
for(int i = 0; i < 5; i++) {
customiza1();
customiza2();
}
}
}
// ConcreteClass
class ClasseConcreta extends ClasseAbstracta {
void customiza1() {
System.out.print("Ol ");
}
void customiza2() {
System.out.println("Mundo!");
}
}
public class ClienteTemplateMethod {
ClasseConcreta app = new ClasseConcreta();
public static void main(String args[]) {
new ClienteTemplateMethod();
}
}
Anacleto Correia
102
IPS-ESTSetbal
//
//
//
//
//
Ol
Ol
Ol
Ol
Ol
Padres de Desenho
Mundo!
Mundo!
Mundo!
Mundo!
Mundo!
Anacleto Correia
103
IPS-ESTSetbal
Padres de Desenho
Visitor (Visitante)
Representa um mtodo a ser executado sobre os elementos de uma
estrutura de objectos. O padro Visitor permite que se defina um
novo mtodo sem alterar as classes dos elementos sobre os quais o
mtodo age.
Visitor promove a extenso de funcionalidades atravs da criao de
classes que obedeam a uma interface comum. Esta interface, Visitor
(Visitante), especifica sobre que objectos os mtodos podero ser
executados, definindo um mtodo visitar(ObjetoX o) para cada
ObjetoX possvel. Os mtodos so codificadas ento em classes que
implementam Visitante, o que permite que se crie novos mtodos,
mas no permite que se altere os objectos sobre os quais operam. Os
objectos clientes criam o visitante que quiserem e chamam o mtodo
visitar() para o objecto sobre o qual pretendam operar.
Participantes:
As classes e/ou objectos que participam no padro so:
Visitor
o Declara o mtodo visit para cada classe de
ConcreteElement na estrutura de objectos. O nome do
mtodo e a assinatura, identificam a classe que envia o
pedido visit ao Visitor Isso permite ao visitor determinar a
classe concreta do elemento a ser visitado. Ento o visitor
pode aceder directamente aos elementos, atravs da sua
interface particular.
ConcreteVisitor
o Implementa os mtodos declarados pelo Visitor. Cada
mtodo implementa um fragmento do algoritmo definido
para a correspondente classe ou objecto na estrutura.
ConcreteVisitor fornece o contexto para o algoritmo e
armazena o seu estado local. Este estado, geralmente
acumula resultados durante a passagem pelos elementos
da estrutura.
Element
o Define o mtodo Accept que recebe um visitor como
argumento.
ConcreteElement
o Implementa o mtodo Accept que recebe um visitor como
argumento.
ObjectStructure
o Pode enumerar os seus elementos
Anacleto Correia
104
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
105
IPS-ESTSetbal
Padres de Desenho
Exemplo
// Padro Visitor
import java.util.ArrayList;
// Aplicao Cliente
public class PatVisitor {
public static void main(String[] args) {
// Carregamento de uma collection de empregado
Empregados e = new Empregados();
e.adicionar(new Administrativo());
e.adicionar(new DirectorDepartamento());
e.adicionar(new DirectorGeral());
// Empregados so 'visitados'
e.aceitar(new RendimentoVisitado());
e.aceitar(new FeriasVisitado());
}
}
// "Visitor"
interface IVisitor {
void visitar(Elemento elemento);
}
// "ConcreteVisitor1"
class RendimentoVisitado
implements IVisitor {
public void visitar(Elemento elemento) {
Empregado empregado = (Empregado) elemento;
// D 10% de aumento de ordenado
empregado.setRendimento(empregado.getRendimento() * 1.10);
System.out.println(empregado.getClass().getName() + " " +
empregado.getNome() + " - novo salrio: " +
empregado.getRendimento());
}
}
// "ConcreteVisitor2"
Anacleto Correia
106
IPS-ESTSetbal
Padres de Desenho
class FeriasVisitado
implements IVisitor {
public void visitar(Elemento elemento) {
Empregado empregado = (Empregado) elemento;
// D 3 dias extra de frias
empregado.setDiasFerias(empregado.getDiasFerias() + 3);
System.out.println(empregado.getClass().getName() + " " +
empregado.getNome() + " - nova durao das frias: " +
empregado.getDiasFerias());
}
}
class Administrativo
extends Empregado {
// Constructor
public Administrativo() {
super("Pedro", 25000.0, 14);
}
}
class DirectorDepartamento
extends Empregado {
// Constructor
public DirectorDepartamento() {
super("Elias", 35000.0, 16);
}
}
class DirectorGeral
extends Empregado {
// Construtor
public DirectorGeral() {
super("Duarte", 45000.0, 21);
}
}
// "Elemento"
abstract class Elemento {
public abstract void aceitar(IVisitor visitor);
}
// "ConcreteElement"
class Empregado
extends Elemento {
String nome;
double rendimento;
int diasFerias;
// Construtor
public Empregado(String nome, double rendimento,
int diasFerias) {
this.nome = nome;
this.rendimento = rendimento;
this.diasFerias = diasFerias;
}
// Propriedades
public String getNome() {
return nome;
}
public void setNome(String value) {
nome = value;
}
public double getRendimento() {
return rendimento;
}
public void setRendimento(double value) {
rendimento = value;
}
public int getDiasFerias() {
return diasFerias;
}
Anacleto Correia
107
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
108
IPS-ESTSetbal
Padres de Desenho
Anacleto Correia
109
IPS-ESTSetbal
Padres de Desenho
Referncias
http://www.jablo.com.br/page/engenho/
Patterns in C#
http://www.dofactory.com/Patterns/PatternBuilder.aspx
Patterns Home Page - http://hillside.net/
Pattern Index - http://c2.com/cgi/wiki?PatternIndex
Design Patterns in Java -http://www.fluffycat.com/java/patterns.html
Duell, Michael, Non-Software Examples of Software Design Patterns http://www2.ing.puc.cl/~jnavon/IIC2142/patexamples.htm
Anacleto Correia
110