Você está na página 1de 110

Padres de Desenho de Software

Texto de apoio disciplina de:

Programao Orientada por Objectos

2 Ano Engenharia Informtica


3 Ano Engenharia Electrnica e de Computadores

Instituto Politcnico de Setbal Escola Superior de Tecnologia

Docente: Anacleto Correia


11/10/2005

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:

Permite aprender com a experincia de outros;


Utilizar solues amplamente testadas;
Utilizar uma linguagem comum entre os designers e
programadores. Melhora-se assim a comunicao entre a
equipa e a documentao dos sistemas;
Utilizar boas prticas no desenvolvimento de software orientado
a objectos, e obtm-se produtos de melhor qualidade.

Anacleto Correia

IPS-ESTSetbal

Padres de Desenho

Padres de Desenho GoF


Erich Gamma, John Vlissides, Ralph Jonhson e Richard Helm,
conhecidos como The Gang of Four (GoF), inspiraram-se no livro de
Alexander e escreveram Design Patterns: Elements of Reusable
Object-Oriented Software, onde descreveram 23 padres de
desenho de software orientado por objectos.
Os 23 padres GoF so geralmente agrupados nas trs seguintes
categorias:

Padres de Criao (Creational): Abstract Factory, Builder,


Factory Method, Prototype, Singleton.
Padres de Estrutura (Structural): Adapter, Bridge,
Composite, Decorator, Facade, Flyweight, Proxy.
Padres de Comportamento (Behavioural): Chain of
Responsibility, Command, Interpreter, Iterator, Mediator,
Memento, Observer, State, Strategy, Template Method, Visitor.

Anacleto Correia

IPS-ESTSetbal

Classe

Padres de Desenho

De Criao
Factory Method

Objecto Abstract Factory


Builder
m
Prototype
b
i
Singleton
t
o

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

Os padres referidos, podem tambm ser divididos, segundo a


classificao de Steven Metsker no seu livro Design Patterns Java
Workbook, em cinco categorias:

Padres de Interface: Adapter, Bridge, Composite e Faade;


Padres de Responsabilidade: Chain of Responsibility,
Flyweight, Mediator, Observer, Proxy e Singleton;
Padres de Construo: Abstract Factory, Builder, Factory
Method, Memento e Prototype;
Padres de Operao: Command, Interpreter, State,
Strategy e Template Method;
Padres de Extenso: Decorator, Iterator e Visitor.

a primeira das categorias referidas, que servir de base


introduo aos padres de desenho que em seguida se far.

Anacleto Correia

IPS-ESTSetbal

Padres de Desenho

No quadro seguinte resume-se a funcionalidade intrnseca a cada um


dos padres de desenho.
Padres Criao
Abstract Factory
Builder
Factory Method
Prototype
Singleton
Padres Estruturais
Adapter
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
Padres Comportamento
Chain of Resp.
Command
Interpreter
Iterator
Mediator
Memento
Observer
State
Strategy
Template Method
Visitor

Anacleto Correia

Tm a ver com a instanciao de objectos.


Fornece uma interface para criar e instanciar famlias
de objectos relacionados, sem especificar classes
concretas
Separa a construo do objecto da sua representao
Cria uma instncia de vrias classes derivadas
Uma instncia completamente inicializada, para ser
copiada ou clonada
Uma classe da qual s pode existir uma nica instncia
Tm a ver com a composio de classes ou objectos
Concilia interfaces de diferentes classes
Separa a interface de um objecto da sua
implementao
Uma estrutura em rvore de objectos simples e
compostos
Adiciona dinamicamente responsabilidades a objectos
Uma nica classe representa um subsistema completo
Uma instncia de pequena granularidade para partilha
eficiente
Um objecto que representa outro objecto
Caracterizam formas de interaco entre classes e
objectos
Uma forma de enviar um pedido entre uma cadeia de
objectos.
Encapsula um comando num objecto
Uma forma de incluir elementos da linguagem num
programa.
Acesso sequencial a elementos de uma coleco.
Define comunicao simplificada entre classes
Captura e restaura o estado interno de um objecto
Uma forma de notificar alteraes num nmero de
classes.
Altera o comportamento de um objecto quando o seu
estado muda.
Encapsula um algoritmo numa classe
Difere os passos concretos de um algoritmo para uma
subclasse
Define uma nova operao para uma classe sem
alteraes

IPS-ESTSetbal

Padres de Desenho

Padres de Criao
So padres que tm a ver com a instanciao de objectos.

Abstract Factory (Fbrica Abstracta)


Fornece uma interface para criar famlias de objectos relacionados ou
interdependentes sem especificar as suas classes concretas.
A fbrica abstracta semelhante ao mtodo-fbrica. Existe uma
classe conhecida pelo cliente que a Fbrica Abstracta. Esta fbrica
capaz de produzir alguns objectos e possui diversas
implementaes, cada uma capaz de construir instncias de
implementaes diferentes dos objectos que a fbrica capaz de
produzir. Dependendo da situao, o cliente ir obter uma instncia
da fbrica de um determinado tipo, de maneira que passar a
construir objectos daquele tipo pela fbrica.
Participantes:
As classes e/ou objectos que participam no padro so:

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

Exemplo do padro no mundo real

Este padro encontrado nos equipamentos de estampagem de


folhas de metal, utilizados na produo automvel. O equipamento de
estampagem uma fbrica abstracta que cria as peas da carroaria
do automvel. O mesmo equipamento utilizado para estampar o
capo, pra-lamas e portas (dianteira e traseira, esquerda e direita),
tampa do porta-malas, etc., de diferentes modelos de automveis. A
troca dos moldes de estampagem efectuada atravs de plataformas
deslizantes. As classes concretas produzidas pelo equipamento
podem ser trocadas em apenas trs minutos.

Anacleto Correia

10

IPS-ESTSetbal

Padres de Desenho

Exemplo

// Abstract Factory pattern


/// classe de teste do Jogo
public class Jogo
{
public static void main(String[] args)
{
// Criar e executar o Mundo Animal de Africa
FabricaContinente africa = new FabricaAfrica();
MundoAnimal mundo = new MundoAnimal( africa );
mundo.executaCadeiaAlimentar();
// Criar e executar o Mundo Animal da America
FabricaContinente america = new FabricaAmerica();
mundo = new MundoAnimal( america );
mundo.executaCadeiaAlimentar();
}
}
// "AbstractFactory"
abstract class FabricaContinente
{
// Mtodos
abstract public Herbivoro criarHerbivoro();
abstract public Carnivoro criarCarnivoro();
}
// "ConcreteFactory1"
class FabricaAfrica extends FabricaContinente
{
// Mtodos
public Herbivoro criarHerbivoro()
{

Anacleto Correia

11

IPS-ESTSetbal

Padres de Desenho

return new Antilope();


}
public Carnivoro criarCarnivoro()
{
return new Leao();
}
}
// "ConcreteFactory2"
class FabricaAmerica extends FabricaContinente
{
// Mtodos
public Herbivoro criarHerbivoro()
{
return new Bisonte();
}
public Carnivoro criarCarnivoro()
{
return new Lobo();
}
}
// "AbstractProductA"
abstract class Herbivoro
{
abstract public String toString();
abstract public void pasta();
}
// "AbstractProductB"
abstract class Carnivoro
{
// Mtodos
abstract public void devora( Herbivoro h );
abstract public String toString();
}
// "ProductA1"
class Antilope extends Herbivoro
{
public String toString()
{
return "Antilope";
}
public void pasta()
{
System.out.println( "Antilope pasta na savana");
}
}
// "ProductB1"
class Leao extends Carnivoro
{
// Mtodos
public void devora( Herbivoro h )
{
// caa Antilope
System.out.println( this + " caa o " + h );
}
public String toString()
{
return "Leao";
}
}
// "ProductA2"

Anacleto Correia

12

IPS-ESTSetbal

Padres de Desenho

class Bisonte extends Herbivoro


{
public String toString()
{
return "Bisonte";
}
public void pasta()
{
System.out.println( "Bisonte pasta na pradaria");
}
}
// "ProductB2"
class Lobo extends Carnivoro
{
// Mtodos
public void devora( Herbivoro h )
{
// caa Bisonte
System.out.println( this + " caa o " + h );
}
public String toString()
{
return "Lobo";
}
}
// "Client"
class MundoAnimal
{
// Variveis de Instncia
private Herbivoro herbivoro;
private Carnivoro carnivoro;
// Constructores
public MundoAnimal( FabricaContinente fabrica )
{
carnivoro = fabrica.criarCarnivoro();
herbivoro = fabrica.criarHerbivoro();
}
// Mtodos
public void executaCadeiaAlimentar()
{
herbivoro.pasta();
carnivoro.devora( herbivoro );
}
}
//
//
//
//

Antilope pasta na savana


Leao caa o Antilope
Bisonte pasta na pradaria
Lobo caa o Bisonte

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

Exemplo do padro no mundo real

Este padro utilizado em restaurantes fast food para servir as refeies de


crianas. Estas refeies consistem tipicamente num artigo principal, um
acompanhamento, uma bebida, e um brinquedo (e.g., hamburger, batatas
fritas, cola e carro de brinquedo). De notar que pode haver variao no
contedo de uma refeio de criana, mas o processo de construo dessa
refeio, sempre o mesmo. Quer o cliente requisite um hamburger,
cheeseburger, ou pernas de galinha, o processo o mesmo. O empregado de
balco solicita ao pessoal do empacotamento que junte um artigo principal, o
acompanhamento e brinquedo. Estes artigos so colocados de seguida num
saco. A bebida colocada num copo junto do saco. Este processo
semelhante em qualquer restaurante do gnero.

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

Factory Method (Mtodo-Fbrica)


Define uma interface para criar um objecto, mas deixa as subclasses
decidirem que classe instanciar. O padro Factory Method deixa uma
classe transferir a responsabilidade de instanciao para as suas
subclasses.
O mtodo-fbrica tambm desacopla o cliente dos construtores dos
objectos que deseja criar. Cria-se uma classe abstracta Fbrica e uma
subclasse para cada objecto que se pretende criar. O cliente s
conhece a classe Fbrica e requisita-lhe objectos, tendo por base um
parmetro discriminador.
Participantes:
As classes e/ou objectos que participam no padro so:

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 do padro no mundo real

Os fabricantes de brinquedos de plstico processam moldes de plstico e


injectam partculas de plstico em moldes das formas desejadas. A classe do
brinquedo (carro, cavalo, super heri, etc.) determinada pelo molde.

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

Exemplo flexibilidade de criao de documentos diferentes

// As classes Report e Resume, subclasses de Document (classe base)


// so especializaes da classe Document. O FactoryMethod evocado
// no mtodo construtor da classe base.
// Product
abstract class Page {abstract class Page {
public String toString() {
return this.getClass().getName();
}
}
// ConcreteProduct
class SkillsPage
extends Page {}
// ConcreteProduct
class EducationPage
extends Page {}
// ConcreteProduct
class ExperiencePage
extends Page {}
// ConcreteProduct
class IntroductionPage
extends Page {}

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

ConcretePrototype1 c1 = (ConcretePrototype1) p1.clone();


System.out.println("clone: "+ c1.getId());
// Create second instances and clone it
Prototype p2 = new ConcretePrototype2("II");
ConcretePrototype2 c2 = (ConcretePrototype2) p2.clone();
System.out.println("clone: "+ c2.getId());
}
}
// "Prototype"
abstract class Prototype implements Cloneable
{
private String id;
// Constructor
public Prototype(String id)
{
this.id = id;
}
// Property
public String getId()
{
return id;
}
public abstract Object clone();
}
// "ConcretePrototype1"
class ConcretePrototype1 extends Prototype
{
// Constructor
public ConcretePrototype1(String id)
{
super(id);
}
public Object clone()
{
// Shallow copy
return new ConcretePrototype1(getId());
}
}
// "ConcretePrototype2"
class ConcretePrototype2 extends Prototype
{
// Constructor
public ConcretePrototype2(String id)
{
super(id);
}
public Object clone()
{
// Shallow copy
return new ConcretePrototype2(getId());
}
}
// clone: I
// clone: II
Exemplo do padro no mundo real

Os prottipos de novos produtos so frequentemente construdos


antes da produo definitiva. Nesse caso o prottipo passivo, e no
participa na sua prpria cpia.
Anacleto Correia

26

IPS-ESTSetbal

Padres de Desenho

A diviso mittica de uma clula, tendo por resultado clulas


idnticas, um exemplo de um prottipo que tem um papel activo na
cpia de si prprio, demonstrando assim o padro prottipo. Quando
uma clula se divide, resultam duas clulas com idntico genoma. Por
outras palavras, a clula clona-se a si prpria.

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

public class TestPrototype {


public static void main(String[] args)
{
System.out.println(
"Criando uma Prototype Factory com uma ColherSopa e uma GarfoSalada");
PrototypeFactory prototypeFactory =
new PrototypeFactory(new ColherSopa(),
new GarfoSalada());
AbstractColher colher = prototypeFactory.makeColher();
AbstractGarfo garfo = prototypeFactory.makeGarfo();
System.out.println("Obtendo o nome da Colher e Garfo:");
System.out.println("Colher: " + colher.getColherName() + ", Garfo: " +
garfo.getGarfoName());
System.out.println(" ");
System.out.println(
"Criando uma Prototype Factory com uma SaladaColher e uma GarfoSalada");
prototypeFactory = new PrototypeFactory(new SaladaColher(),
new GarfoSalada());
colher = prototypeFactory.makeColher();
garfo = prototypeFactory.makeGarfo();
System.out.println("Obtendo o nome da Colher e do Garfo:");
System.out.println(
"Colher: " + colher.getColherName() + ", Garfo: " +
garfo.getGarfoName());
}
}
// PrototypeFactory.java
// a Factory for Prototypes
class PrototypeFactory
{
AbstractColher prototypeColher;
AbstractGarfo prototypeGarfo;
public PrototypeFactory(AbstractColher colher, AbstractGarfo garfo) {
prototypeColher = colher;
prototypeGarfo = garfo;
}
public AbstractColher makeColher() {
return (AbstractColher)prototypeColher.clone();
}
public AbstractGarfo makeGarfo() {
return (AbstractGarfo)prototypeGarfo.clone();
}
}
// AbstractColher.java
// One of Two Prototypes
abstract class AbstractColher implements Cloneable
{

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

Criando uma Prototype Factory com uma ColherSopa e uma GarfoSalada


Obtendo o nome da Colher e Garfo:
Colher: Colher Sopa, Garfo: Garfo Salada

Criando uma Prototype Factory com uma SaladaColher e uma GarfoSalada


Obtendo o nome da Colher e do Garfo:
Colher: Colher Salada, Garfo: 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.

Exemplo do padro no mundo real

O mandato do Presidente da Repblica de um pas um Singleton. A


Constituio do pas especifica a forma de eleio, o fim do mandato
e a forma de sucesso. Como consequncia, s pode existir um nico
Presidente em actividade em determinado momento.
Independentemente da identidade da pessoa que ocupa a
presidncia, o ttulo de Presidente da Repblica um ponto de
acesso que identifica qualquer pessoa que exera o mandato.

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

public static GlobalVars getInstance() {


if (instance==null) {
// instanciao ocorre apenas se um objecto for solicitado
instance = new GlobalVars();
}
return instance;
}
}
public class TestaGlobalVars {
private GlobalVars globais;
public TestaGlobalVars() {
globais = GlobalVars.getInstance();
}
public void imprimeVariaveis(GlobalVars gv) {
System.out.println("inteiro = " + gv.inteiro);
System.out.println("real = " + gv.real);
}
public void ajustaVariaveis(GlobalVars gv, int i, float r) {
gv.inteiro = i;
gv.real = r;
}
public void teste() {
System.out.println("1/a Instancia");
imprimeVariaveis(globais);
ajustaVariaveis(globais, -50, 30.69f);
imprimeVariaveis(globais);
// tentativa de criar outra instncia
GlobalVars duplicata = GlobalVars.getInstance();
System.out.println("Duplicado");
imprimeVariaveis(duplicado);
ajustaVariaveis(duplicata, 20, -10.85f);
imprimeVariaveis(duplicado);
System.out.println("1/a Instancia");
imprimeVariaveis(globais);
}
public static void main(String a[]) {
new TestaGlobalVars().teste();
}
}
/*
1/a Instancia
inteiro = 0
real = -1.0
inteiro = -50
real = 30.69

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

Exemplo do padro no mundo real

As chaves de encaixes so um exemplo de adaptador. Um encaixe


pode ser adaptado a uma cremalheira, desde que o tamanho das
guias seja o mesmo. As guias tpicas, nos EUA, tm dimenses de
1/2" e 1/4". Naturalmente que uma guia de uma cremalheira de 1/2",
no se ajusta a uma guia de encaixe de 1/4", a no ser que seja
utilizado um adaptador. Um adaptador de 1/2" para 1/4" tem uma
fmea de 1/2" para se ajustar s guias de 1/2" da cremalheira e um
macho de 1/4" para se ajustar aos guias do encaixe de 1/4".

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.

Funo das classes participantes:

Abstraction - Define a interface da abstraco e mantm uma


referncia para um objecto do tipo Implementor;
RefinedAbstraction Estende a interface definida por
Abstraction;
Implementor Define a interface para as classes que
realizam a implementao; no necessita de corresponder
exactamente interface de Abstraction;
ConcreteImplementor Implementa a interface de
Implementor.

Anacleto Correia

39

IPS-ESTSetbal

Padres de Desenho

Exemplo do padro no mundo real

Um interruptor domstico, utilizado para controlo da iluminao,


ventilao, etc., um exemplo de Bridge. O objectivo de um
interruptor o de ligar ou desligar um dispositivo. O interruptor
concreto pode ser implementado como um interruptor de duas
posies, de deslocamento, de brilho, etc.

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 do padro no mundo real

As expresses aritmticas so Composites (compostos). Uma


expresso aritmtica consiste num operando, um operador (+ - * /) e
outro operando. O operando pode ser um nmero, ou uma expresso
aritmtica. Assim, ambas expresses 5 + 6 e (1 + 4) + (5 * 2) so
vlidas.

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 do padro no mundo real

Embora as telas se possam pendurar na parede com ou sem moldura,


esta so frequentemente utilizada, e a moldura do quadro que
realmente pendurada parede. Antes de serem penduradas, as
telas podem ser encaixilhadas e emolduradas. A tela, o caixilho e a
moldura do forma a um nico componente visual.

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 do padro no mundo real

Os clientes encontram uma fachada (front-office) ao encomendar a


partir de um catlogo. O cliente telefona para um nmero e fala com
um funcionrio de atendimento ao pblico. O funcionrio age como
uma fachada, fornecendo uma interface dos servios de recepo de
encomendas, de cobrana e expedio de encomendas.

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

System.out.println("Verificar emprstimos de " + c.getName());


return true;
}
}
class Cliente {
private String name;
// Construtor
public Cliente(String name) {
this.name = name;
}
// propriedade
public String getName() {
return name;
}
}
// "Facade"
class PedidoEmprestimo {
private Banco banco = new Banco();
private Emprestimo emprestimo = new Emprestimo();
private Credito credito = new Credito();
public boolean ehEligivel(Cliente cust, int amount) {
System.out.println("\n" + cust.getName() + " pretende " + amount +
" de emprestimo\n");
boolean eligivel = true;
// Verifica posio financeira do cliente
if (!banco.temPoupancasSuficientes(cust, amount)) {
eligivel = false;
}
else if (!emprestimo.naoTemEmprestimos(cust)) {
eligivel = false;
}
else if (!credito.temCredito(cust)) {
eligivel = false;
}
return eligivel;
}
}
/*
Ana Silva pretende 125000 de emprestimo
Verificar poupanas de Ana Silva
Verificar emprstimos de Ana Silva
Verificar credito de Ana Silva
Emprstimo de Ana Silva foi Aprovado
*/

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 do padro no mundo real

A rede de telefone pblica comutada um exemplo de um flyweight.


H diversos recursos tais como geradores de tom, geradores de
toque e receptores de dgitos que so partilhados por todos os
subscritores. Um subscritor no tem ideia de quantos recursos esto
na pool quando levanta o auscultador para fazer uma chamada. O
que lhe interessa apenas obter o tom, se os dgitos seleccionados
so recebidos e a chamada efectuada.

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

o Define a interface comum a RealSubject e Proxy de forma


que a Proxy possa ser usada em qualquer local onde
RealSubject seja esperado.
RealSubject
o Define o objecto real que a proxy representa.

Anacleto Correia

60

IPS-ESTSetbal

Padres de Desenho

Exemplo do padro no mundo real

Uma letra ou um cheque de uma pessoa uma proxy de um depsito


ordem num banco do qual seja cliente. Um cheque pode ser
utilizado em vez de dinheiro para efectuar compras e em ltima
instncia aceder ao depsito ordem na conta do cliente.

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.

Chain of Responsibility (Cadeia de Responsabilidade)


Evita acoplar o objecto que envia um pedido ao receptor do mesmo,
dando oportunidade a vrios objectos de tratarem esse pedido. Os
objectos receptores so encadeados e o pedido passado na cadeia
at que um objecto o trate.
montada uma cadeia de objectos que podem servir um
determinado pedido. Em vez de acoplar o cliente a um objecto
especfico para a execuo de um determinado mtodo, o pedido
enviado cadeia. O pedido vai passando pelos objectos at encontrar
o mais adequado para satisfaz-lo, ou ento, cada objecto realiza
uma parte do servio e passa o pedido ao objecto seguinte na cadeia.
Um exemplo dessa ltima verso so os interceptores do Xwork: ao
executar uma aco, o pedido passa antes pelos interceptores, que
realizam um tipo de servio antes da aco executar.
Participantes:
As classes e/ou objectos que participam no padro so:

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 do padro no mundo real

As mquinas de separao de moedas utilizadas pelos bancos so um


exemplo de Cadeia de Responsabilidades. Em vez de possurem
ranhuras diferentes por cada tipo de moeda, existe apenas uma.
Quando a moeda cai, encaminhada para um receptculo adequado
dimenso da moeda, atravs de mecanismos internos apropriados.

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 do padro no mundo real

O bilhete de pedido de uma refeio um exemplo do padro


Command. O empregado de mesa recebe o pedido de um cliente e
encapsula-o registando no bilhete. O pedido ento colocado na fila
das refeies a preparar. De notar que o bloco de notas, utilizado em
diferentes refeies, no depende do menu, por isso, pode suportar
pedidos de diferentes refeies.

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

public void add(Command c) {


pedidos.add(c);
}
public void correr() {
Iterator it = pedidos.iterator();
while (it.hasNext())
( (Command) it.next()).executar();
}
}
// Client
// Cria o ConcreteCommand e define o seu receptor
public class CommandPattern {
private static Macro macro = new Macro();
public static void teste() {
macro.add(new Ola(new ReceptorOla()));
macro.add(new Mundo(new ReceptorMundo()));
macro.add(new EuSou(new ReceptorEuSou()));
macro.correr();
}
public static void main(String args[]) {
teste();
}
}
/*
Sou o Receiver de Ola!
Sou o Receiver de Mundo!
Sou o Receiver de EuSou!
*/

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

Exemplo do padro no mundo real

Os msicos so exemplos de intrpretes. O compasso e durao de


uma nota pode ser representada em notao musical. Essa notao
a linguagem da msica. Os msicos que tocam msica a partir de
uma pauta, podem reproduzir o compasso e a durao originais, das
notas representadas.

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.

Exemplo do padro no mundo real

Nos televisores os botes do comando remoto, anterior e


seguinte, so utilizados para percorrer os canais. Quando o
Anacleto Correia

75

IPS-ESTSetbal

Padres de Desenho

espectador navega atravs desses botes pelos canais, o nmero do


canal no importante, apenas o programa visualizado. Se o
programa visualizado na altura, no tiver interesse, o espectador
pode passar ao canal seguinte, atravs do boto seguinte, sem
saber o seu nmero para o qual vai.

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

public Object next() {


return p[++pos];
}
}
public static final int CAPACIDADE = 1000;
private int capacidade;
private Object p[];
private int topo = -1;
public PilhaArray() {
this(CAPACIDADE);
}
public PilhaArray(int cap) {
capacidade = cap;
p = new Object[capacidade];
}
public int tamanho() {
return (topo + 1);
}
public boolean estaVazia() {
return (topo < 0);
}
public void empilha(Object obj) {
if (tamanho() != capacidade)
p[++topo] = obj;
}
public Object topo() {
if (!estaVazia())
return p[topo];
return null;
}
public Object desempilha() {
if (!estaVazia()) {
Object elem = p[topo];
p[topo--] = null;
return elem;
}
return null;
}
public Iterator getIterator() {
return new PilhaArrayIterator();
}
}
//Cliente
public class PatIterator {
public static void main(String args[]) {
Iterator ai, ai2;
PilhaArray s;
s = new PilhaArray();
for (int i = 0; i < 5; i++)
s.empilha(new Integer(i));
ai = s.getIterator();

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 do padro no mundo real

A torre de controlo de um aeroporto demonstra este padro. Os


pilotos dos avies que se aproximam ou partem, comunicam com a
torre, em vez de comunicarem entre si. As restries de quem pode
aterrar ou levantar voo so definidas pela torre. importante notar,
que a torre no controla todo o voo de um avio. A sua funo
apenas estabelecer as restries relativas ao acesso e largada do
aeroporto.

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

public void registar(Participante participante) {


if (participantes.get(new Integer(participante.getNome().hashCode())) == null) {
participantes.put(new Integer(participante.getNome().hashCode()),
participante);
}
participante.setSala(this);
}
public void enviar(
String de, String para, String mensagem) {
Participante pto = (Participante) participantes.get(
new Integer(para.hashCode()));
if (pto != null) {
pto.receber(de, mensagem);
}
}
}
// "AbstractColleague"
class Participante {
private SalaConversacao salaConversacao;
private String nome;
// Construtor
public Participante(String nome) {
this.nome = nome;
}
// Propriedades
public String getNome() {
return nome;
}
public SalaConversacao getSala() {
return salaConversacao;
}
public void setSala(SalaConversacao salaConversacao) {
this.salaConversacao = salaConversacao;
}
public void enviar(String para, String mensagem) {
salaConversacao.enviar(nome, para, mensagem);
}
public void receber(
String de, String mensagem) {
System.out.println(de + " a " + getNome() + ": '" + mensagem + "'");
}
}
//" ConcreteColleague1"
class Beatle
extends Participante {
// Construtor
public Beatle(String nome) {
super(nome);
}
public void receber(String de, String mensagem) {
System.out.print("Para um Beatle: ");
super.receber(de, mensagem);
}
}
//" ConcreteColleague2"
class NaoBeatle
extends Participante {
// Construtor
public NaoBeatle(String nome) {
super(nome);
}
public void receber(String de, String mensagem) {
System.out.print("Para um no-Beatle: ");
super.receber(de, mensagem);

Anacleto Correia

81

IPS-ESTSetbal

Padres de Desenho

}
}
/*
Para
Para
Para
Para
Para
*/

um
um
um
um
um

Beatle: Yoko a John: 'Hi John!'


Beatle: Paul a Ringo: 'All you need is love'
Beatle: Ringo a George: 'My sweet Lord'
Beatle: Paul a John: 'Can't buy me love'
no-Beatle: John a Yoko: 'My sweet love'

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

Exemplo do padro no mundo real

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

// Restore saved state


s.RecuperarMemento(m.getMemento());
}
}
// "Originator"
class PrevisaoVendas {
private String nome;
private String telefone;
private double orcamento;
// Propriedades
public String getNome() {
return nome;
}
public void setNome(String valor) {
nome = valor;
System.out.println("Nome: " + nome);
}
public String getTelefone() {
return telefone;
}
public void setTelefone(String valor) {
telefone = valor;
System.out.println("Telefone: " + telefone);
}
public double getOrcamento() {
return orcamento;
}
public void setOrcamento(double valor) {
orcamento = valor;
System.out.println("Orcamento: " + orcamento);
}
public Memento GuardarMemento()
{
System.out.println("\nGuardar estado --\n");
return new Memento(nome, telefone, orcamento);
}
public void RecuperarMemento(Memento memento)
{
System.out.println("\nRecuperar estado --\n");
this.setNome(memento.getNome());
this.setTelefone(memento.getTelefone());
this.setOrcamento(memento.getOrcamento());
}
}
// "Memento"
class Memento {
private String nome;
private String telefone;
private double orcamento;
// Construtor
public Memento(String nome, String telefone, double orcamento)
{

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.

Exemplo do padro no mundo real

Os leiles demonstram este padro. Cada licitante possui uma


tabuleta numerada, que usada para indicar a sua licitao. O
licitador inicia o leilo, e vai observando se alguma tabuleta
erguida, em sinal de aceitao do preo licitado. Essa aceitao vai
fazer alterar esse preo, sendo o novo preo difundido por todos os
licitantes.

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

Exemplo do padro no mundo real

Este padro pode ser observado nas mquinas de venda automtica.


O estado dessas mquinas, funo da disponibilidade de produtos,
possibilidade de efectuar trocos, do artigo seleccionado, etc. Quando
depositada uma quantia e seleccionado um produto, podem ocorrer
em funo do estado da mquina as seguintes respostas: entrega do
produto sem troco, entrega do produto com troco, no entrega do
produto devido a insuficincia de troco ou no entrega do produto
devido sua inexistncia.

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

public void pagarJuro() {


estado.pagarJuro();
System.out.println("Pagamento Juro --- ");
System.out.println(" Saldo = " + this.getSaldo());
System.out.println(" Estado = " +
this.getEstado().getClass().getName());
}
}
/*
Depsito --- 500.0
Saldo = 500.0
Estado = EstadoPrata
Depsito --- 300.0
Saldo = 800.0
Estado = EstadoPrata
Depsito --- 550.0
Saldo = 1350.0
Estado = EstadoOuro
Pagamento Juro --Saldo = 1417.5
Estado = EstadoOuro
Levantamento --- 2000.0
Saldo = -582.5
Estado = EstadoVermelho
No existem fundos disponveis para levantamento!
Levantamento --- 1100.0
Saldo = -597.5
Estado = EstadoVermelho
*/

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 do padro no mundo real

Os tipos de transporte para o aeroporto de uma cidade so um


exemplo de Strategy. Existem vrias opes, tais como a conduo
da viatura ligeira particular, tomar um txi, um autocarro, o metro,
etc. Qualquer dos meios pode ser utilizado de forma alternativa. O
viajante dever seleccionar o meio adequado, em funo do custo,
proximidade e tempo disponvel.

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

Template Method (Mtodo-Modelo)


O padro Template Method define o esqueleto de um algoritmo num
mtodo, permitindo que as subclasses completem algumas das
etapas. permitido assim s subclasses, que redefinam determinadas
etapas de um algoritmo sem alterar a sua estrutura.
O padro consiste pois em implementar um mtodo numa classe
abstracta, que evoca um ou mais mtodos abstractos. Ou seja, parte
da implementao daquele mtodo fica delegada s subclasses, que
tero que implementar os mtodos abstractos. Por exemplo, pode-se
criar uma classe utilitria (para reutilizao) que defina uma janela
com alguns botes, mas deixar s subclasses a tarefa de implementar
o que dever ser efectuado quando os botes forem accionados.
Participantes:
As classes e/ou objectos que participam no padro so:

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 do padro no mundo real

Os construtores civis utilizam o Template Method quando constroem


vivendas. Uma vivenda tpica consiste num nmero limitado de
assoalhadas, que tem um tipo de acabamento. As fundaes,
canalizao, instalao elctrica, so idnticas em todas as vivendas.
Os acabamentos s sero efectuados em fases posteriores da
construo, de forma a colocar no mercado uma diversidade de
modelos de vivendas.

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

o Pode fornecer uma interface de alto-nvel, para permitir o


visitor visitar os seus elementos.
o Pode ser um padro Composite ou uma collection list ou
set.

Anacleto Correia

105

IPS-ESTSetbal

Padres de Desenho

Exemplo do padro no mundo real

Este padro pode ser observado no modo de operao das empresas


de txis. Quando algum chama um txi (Visitor), passa a fazer parte
da lista de clientes em espera. A empresa envia ento um txi ao
cliente (que aceita o Visitante). Aps entrar no txi, o cliente deixa de
ter controlo sobre o seu transporte, passando o mesmo para a
responsabilidade do txi.

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

public void setDiasFerias(int value) {


diasFerias = value;
}
public void aceitar(IVisitor visitor) {
visitor.visitar(this);
}
}
// "ObjectStructure"
class Empregados {
private ArrayList empregados = new ArrayList();
public void adicionar(Empregado empregado) {
empregados.add(empregado);
}
public void remover(Empregado empregado) {
empregados.remove(empregado);
}
public void aceitar(IVisitor visitor) {
for (int i = 0; i < empregados.size(); i++) {
( (Empregado) empregados.get(i)).aceitar(visitor);
}
System.out.println();
}
}
/*
Administrativo Pedro - novo salrio: 27500.00
DirectorDepartamento Elias - novo salrio: 38500.00
DirectorGeral Duarte - novo salrio: 49500.00
Administrativo Pedro - nova durao das frias: 17
DirectorDepartamento Elias - nova durao das frias: 19
DirectorGeral Duarte - nova durao das frias: 24
*/

Anacleto Correia

108

IPS-ESTSetbal

Padres de Desenho

Relaes entre Padres GoF

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

Você também pode gostar