Beruflich Dokumente
Kultur Dokumente
Padrões
Um padrão de é uma maneira de documentar uma solução conhecida para um problema
usualmente encontrado
O objetivo do padrão é permitir que boas soluções sejam reutilizadas em diferentes projetos
Um padrão de projeto possui 3 partes distintas:
Contexto
Problema recorrente neste contexto
Solução para o problema
Características dos Padrões de Projeto
São observados através da experiência
São descritos de uma forma estruturada
Previnem contra a “reinvenção da roda”
Existem em diferentes níveis de abstração
Estão em desenvolvimento contínuo
São artefatos reutilizáveis
Transmitem melhores práticas
Permitem o uso de um vocabulário comum
Podem ser utilizadas em conjunto para resolver um problema mais amplo
Classificação de Padrões
Padrões
Os padrões de projeto podem ser classificados de acordo
com a fase de desenvolvimento em que são mais
adequados:
Padrões de Análise (Analysis patterns)
Seu foco é na fase de análise ou modelamento de negócio
Muita das vezes os padrões estão ligados ao domínio do problema o que
pode
Padrões de Arquitetura (Architectural patterns)
Seu foco é na arquitetura do software
Padrões de Projeto (Design patterns)
Foco no projeto de componentes do software
Muitas das vezes os padrões podem estar muito ligados tanto ao
domínio da solução, quanto do problema
1
10/6/2011
Classificação de Padrões
Padrões
Padrões de Análise (Analysis patterns)
Martin Fowler , 1996
Padrões de Arquitetura (Architectural patterns)
Apresentado inicialmente por Frank Buschmann et al., 1996
Computação Distribuída - Frank Buschmann et al., 2007
Padrões de Projeto (Design patterns)
GOF (Gang of Four) E. Gamma, R. Helm, R. Johnson, J. Vlissides – 1995
Aplicações Concorrentes e em Rede - Frank Buschmann et al. – 2000
Enterprise Integration Patterns – Gregor Hohpe, 2003
Real-time Design Patterns – Bruce Douglass, 2003
.Net Design Patterns - Christian Thilmany, 2003
J2EE Design Patterns - Deepak Alur, 2003
Web Services Patterns – Paul Monday, 2003
Ajax Design Patterns - Michael Mahemoff, 2006
SOA Design Patterns – Thomas Erl, 2009
Programação Orientada a Objetos 2 58
Flávio de Oliveira Silva, M.Sc.
Padrões de Análise
(Analysis Patterns)
Proposto por Martin Fowler, em livro publicado em 1996
Notação do Livro não é baseada em UML
Baseada em áreas (domínios) específicas como: manufatura; financeira e saúde
Mesmo assim
assim, padrões podem apresentados podem ser úteis em outros
domínios
Alguns princípios apresentados
Um modelo não está certo ou errado, eles podem ser mais ou menos úteis
Modelos conceituais estão ligados a tipos (interfaces) e não implementações (classes)
Padrões são o ponto de partida, não o destino
Sempre que possível, quando existir um tipo e um supertipo, considere colocar os
recursos no supertipo, desde que isto faça sentido
Quando
Q d múltipos
úl i atributos
ib possuam um comportamento relacionado
l i d e presente em
muitos tipos, combine estes atributos em um novo tipo fundamental
2
10/6/2011
Padrões de Análise
(Analysis Patterns)
Exemplos de alguns padrões de projeto
Quantity (3.1)
Conversion Ratio (3.2)
C
Compound dU it (3
Units 3)
(3.3)
Measurement (3.4)
Observation (3.5)
Range (4.3)
Name (5.1)
Account (6.1)
Transaction (6.2)
Summary
S Account
A (6.3)
(6 3)
Plan (8.4)
Contract (9.1)
Product (10.3)
Associative Type (15.1)
Padrões de Projeto
GoF
Trabalho proposto inicialmente por Erich Gamma, Richard Helm, Ralph
Jonhson, John Vlissides (Gang of Four) em 1995
Famílias de Padrões
D C
De i ã
Criação
Responsáveis pela criação de objetos
Permitem que o sistema fique independente da forma como os objetos são criados
Estruturais
Relacionados com a forma com que classes e objetos são compostos a fim de
formar estruturas maiores
Comportamentais
Relacionados com a atribuição de responsabilidades entre objetos
Descrevem a comunicação entre objetos
3
10/6/2011
Padrões de Criação
Factory
Fornece uma interface para criar um objeto, porém a decisão de qual classe será
instanciada é decidida pelas subclasses
Abstract Factoryy
Fornecem uma interface para criação de objetos sem especificar sua classe concreta
Singleton
Garante que apenas uma classe possua uma única instância e oferece um acesso
global à mesma
Builder
Permite separar a construção de um objeto complexo de sua representação a fim de
que diferentes objetos sejam criados através do mesmo processo
Prototype
Permite que um objeto seja criado a partir de uma instância existente copiando suas
propriedades
Factory
Permite que um objeto seja criado sem que seja necessário informar a
classe exata que será criada
Separa a complexidade de criação do objeto
Uma interface define um método padrão para criação
Subclasses implentam este método e devolvem o objeto desejado
A fábrica implementa o método criando o objeto conforme necessário
class GOF - Factory
«interface»
ImageReader ImageReaderFactory
GifReader JpegReader
4
10/6/2011
Factory
Exemplo
public interface ImageReader {
public DecodedImage getDecodedImage();
}
Factory
Exemplo
public class ImageReaderFactory {
public static ImageReader getImageReader(InputStream is) {
int imageType = determineImageType(is);
switch(imageType)
( g yp ) {
case ImageReaderFactory.GIF:
return new GifReader(is);
case ImageReaderFactory.JPEG:
return new JpegReader(is);
// etc.
}
}
}
5
10/6/2011
Abstract Factory
Permite que objetos sejam criados de forma transparente caso exista um
grupo de diferente fábricas
class Design Pattern - Abstract Factory
A li ti R
ApplicationRunner
+ main(String[]) : void
+ createOsSpecificFactory() : GUIFactory
Application
+ Application(GUIFactory)
«interface» «interface»
GUIFactory Button
+ createButton() : Button + paint() : void
Abstract Factory
interface GUIFactory {
public Button createButton();
}
class WinFactory y implements
p GUIFactory
y{
public Button createButton() {
return new WinButton();
}
}
class OSXFactory implements GUIFactory {
public Button createButton() {
return new OSXButton();
}
}
6
10/6/2011
Abstract Factory
interface Button {
public void paint();
}
class WinButton implements Button {
bli void
public id paint()
i t() {
System.out.println("I'm a WinButton");
}
}
class OSXButton implements Button {
public void paint() {
System.out.println("I'm an OSXButton");
}
}
Abstract Factory
class Application {
public Application(GUIFactory factory) {
Button button = factory.createButton();
button.paint();
}
}
7
10/6/2011
Singleton
Objetivo
Garante que existirá uma única instância de um objeto de uma classe e
permite um acesso global ao mesmo
Motivação
Em muitas situações é necessário um único objeto. Exemplos:
O objeto que representa um sistema de arquivos do Sistema Operacional
Um objeto que representa um arquivo de configuração de uma aplicação
Um objeto que representa uma conexão com um banco de dados
Singleton
Exemplo
public class Singleton {
//instância de um objeto da classe Singleton
//inicializada com a chamada do construtor
private static Singleton instance = new Singleton();
//método
// ét d estático
táti que retorna
t a ú
única
i instância
i tâ i d da classe
l
public static Singleton getInstance() {
return instance;
}
}
8
10/6/2011
Singleton
Exemplo - Outra abordagem
public class Singleton {
// Private constructor prevents instantiation from other classes
private Singleton() {
}
/**
* SingletonHolder is loaded on the first execution of Singleton.getInstance()
* or the first access to SingletonHolder.INSTANCE, not before.
*/
private static class SingletonHolder {
public
bli static
t ti final
fi l Singleton
Si l t instance
i t = new Singleton();
Si l t ()
}
Padrões Estruturais
Adapter
Bridge
Composite
Decorator
Facade
Proxy
9
10/6/2011
Adapter
Objetivo
Converter uma interface de uma classe para uma interface compatível com a
esperada
Permite que classes possam cooperar o que não seria possível pela
incompatibilidade entre as interfaces
Traduz as chamadas de sua interface para chamadas da interface da classe
adaptada
Também conhecida como “Wrapper”
Uso
Este padrão de projeto é útil em situações onde uma classe já existente
p ç q
possui serviços que serão utilizados,, p
porém não na Interface necessária
Por exemplo, uma classe que espera valores boleanos
Adapter
Exemplo
Um novo método para adicionar inteiros será utilizado em uma implementação
O código disponível porém apenas permite a adição de números binários
(BinaryCalulator)
A classe CalculatorAdapter permitirá o uso da implementação disponível
(BinaryCalculator), porém adatapada o
class GOF-Adapter
«interface»
ICalculator
+ add(int, int) : int
CalculatorAdapter
BinaryCalculator
- bcalc: BinaryCalculator
+ add(String, String) : string
+ CalculatorAdapter(bcalc)
+ add(int, int) : int
10
10/6/2011
Adapter
Exemplo
public interface ICalculator{
public int add(int ia , int ib);
}
public class BinaryCalculator
p y {
public static string add(String sa,String sb){ //…
}
}
public class CalculatorAdapter implements ICalculator {
private BinaryCalculator bcalc;
public CalculatorAdapter(bcalc c){
bcalc = c;
}
public int add(int ia, int ib){
String result;
result = bcalc.add(Integer.toBinaryString(ia), Integer.toBinaryString(ib),
//converts binary string to a decimal representation return is value
return Integer.valueOf(result,10).intValue();
}
}
Programação Orientada a Objetos 2 76
Flávio de Oliveira Silva, M.Sc.
Adapter
Outro Exemplo
Dois exemplos de classes adptadoras. Uma baseada em uso
(DListToStackAdapter) e outra em herança múltipla (DListStackAdapter)
class GOF-Adapter
p
«interface» DList
Stack
push(T) : void + insert(DNode, T) : void
+
+ pop() : T + remove(DNode, T) : void
top() : T + insertHead(T) : void
+
+ insertTail(T) : void
+ removeHead() : T
+ removeTail() : T
+ getHead() : T
+ getTail() : T
T
T
p
DListStackAdapter
DListToStackAdapter
11
10/6/2011
Decorator
Objetivo
Permite adicionar responsabilidades a um objeto de forma dinâmica
Desta forma não é necessário criar subclasses a fim de estender a
funcionalidade dos objetos
Motivação
Em alguns casos deseja-se adicionar responsabilidades a um objeto e não a
uma classe inteira
Exemplo
Considere a modelagem de um cardápio de cafés onde é possível acrescentar
diversos acompanhamentos a um café
Como calcular o custo de cada item disponível no cardápio? Criar uma classe para
cada opção não é melhor alternativa
Neste caso o Decorator pode ser uma opção para a modelagem
Decorator
Exemplo
Baseado Capítulo 3, do livro “Head First Design Pattern”
Neste exemplos as bedidas (DarkRoast, Decaf, Espresso, HouseBlend) pode ser
decoradas com diferentes acompanhamentos (Milk, Chocolate, Sugar, Cream)
class
l GOF-Decorator
GOF D t
Beverage
StarbuzzCoffee CondimentDecorator
# description: String = "Unknown Beverage"
+ main(String[]) : void + getDescription() : String
+ getDescription() : String
+ cost() : double
DarkRoast
+ DarkRoast()
+ cost() : double Cream
- beverage: Beverage
Milk
+ Chocolate(Beverage) Sugar
+ getDescription() : String
+ cost() : double - beverage: Beverage
+ Sugar(Beverage)
+ getDescription() : String
+ cost() : double
12
10/6/2011
Decorator
Exemplo - Código
public abstract class Beverage {
protected String description = "Unknown Beverage“;
public String getDescription() {
return description;
p ;
}
public abstract double cost();
}
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
Decorator
Exemplo - Código
public class DarkRoast extends Beverage {
public DarkRoast() { description = "Dark Roast Coffee“; }
public double cost() { return .99; }
}
public class Decaf extends Beverage {
public Decaf() {description = "Decaf Coffee"; }
public double cost() { return 1.05; }
}
13
10/6/2011
Decorator
Exemplo - Código
public class Milk extends CondimentDecorator {
private Beverage beverage;
public Milk(Beverage beverage) { this.beverage = beverage; }
public String
p gggetDescription()
p () {{return beverage.getDescription()
g g p () + ",, Milk";; }
public double cost() { return .10 + beverage.cost(); }
}
public class Chocolate extends CondimentDecorator {
private Beverage beverage;
public Chocolate(Beverage beverage) { this.beverage = beverage; }
public String getDescription() { return beverage.getDescription() + ", Chocolate“; }
public double cost() { return .20 + beverage.cost(); }
}
public class Sugar extends CondimentDecorator {
private Beverage beverage;
public Sugar(Beverage beverage) { this.beverage = beverage; }
public String getDescription() { return beverage.getDescription() + ", Sugar"; }
public double cost() { return .15 + beverage.cost(); }
}
Programação Orientada a Objetos 2 82
Flávio de Oliveira Silva, M.Sc.
Decorator
Exemplo - Código
public class Cream extends CondimentDecorator {
private Beverage beverage;
public Cream(Beverage
p ( g beverage)
g ){
this.beverage = beverage;
}
14
10/6/2011
Decorator
Exemplo - Código
public class StarbuzzCoffee {
public static void main(String args[]) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription()
y p ( g g p () + " $
$" + beverage.cost());
g ());
Beverage beverage2 = new DarkRoast();
beverage2 = new Chocolate(beverage2);
beverage2 = new Milk(beverage2);
beverage2 = new Cream(beverage2);
System.out.println(beverage2.getDescription()+ " $" + beverage2.cost());
Facade
Objetivo
Fornece uma interface comum para um grupo de classes de um subsistema,
facilitando o seu uso
Motivação
Reduzir o acomplamento entre sistemas
class GOF-FACADE
class GOF-FACADE
Class6 Class7
Class6 Class7
Facade
Subsistema Subsistema
Class1 Cl
Class3
3 Class5
Class4
Class2 Class4
Class2
15
10/6/2011
Facade
Exemplo - UML
A facade (TravelFacade) esconde a complexidade para integrar com o sistema
de viagem (TravelSystem)
Facade implementa todo o código necessário para integrar com o sistema
O ideal é definir a fachada como uma interface e então criar sua implementação
concreta class GOF-Facade Sample
«interface»
ITravelFacade
+ getFlightsAndHotels(Date, Data) : void
Trav elFacadeImpl
Client
- hotelBooker: HotelBooker
+ main(String[]) : void - flightBooker: FlightBooker
T
Trav elSystem
lS t
-flightBooker
-hotelBooker
FlightBooker
HotelBooker
Façade
Exemplo - Código
public class HotelBooker{
public ArrayList<Hotel> getHotelNamesFor(Date from, Date to) {
//returns hotels available in the particular date range
}
}
public class FlightBooker{
public ArrayList<Flight> getFlightsFor(Date from, Date to){
//returns flights available in the particular date range
}
}
16
10/6/2011
Façade
Exemplo - Código
public class TravelFacadeImpl implements ITravelFacade{
private HotelBooker hotelBooker;
private FlightBooker flightBooker;
public void g
p getFlightsAndHotels(Date
g ( from,, Data to)) {
ArrayList<Flight> flights = flightBooker.getFlightsFor(from, to);
ArrayList<Hotel> hotels = hotelBooker.getHotelsFor(from, to);
//process and return
}
}
Bridge
Objetivo
Desacoplar a abstração da implementação
Cada um pode ser estendido de forma independente
M ti ã
Motivação
Quando é possível a presença de mais de uma implementação para uma
determinada abstração
Aplicação
Evitar uma ligação forte entre a abstração e a implementação
Permitir que uma implementação seja escolhida em tempo de execução
17
10/6/2011
Bridge
Exemplo
Abstração (Shape) e implementação (DrawingAPI) podem evoluir de
forma independente
class GOF-Bridge
«interface»
BridgePatternClient «interface»
Shape
DrawingAPI
+ main(String[]) : void + draw() : void -drawingAPI + drawCircle(double, double, double) : void
+ resizeByPercentage(double) : void
CircleShape
- x: double
- y: double
- radius: double
- drawingAPI: DrawingAPI
Draw ingAPI2 Draw ingAPI1
+ CircleShape(double, double, double, DrawingAPI)
+ drawCircle(double, double, double) : void + drawCircle(double, double, double) : void
+ draw() : void
+ resizeByPercentage(double) : void
Bridge
Exemplo - Código
/** "Implementor" */
interface DrawingAPI {
public void drawCircle(double x, double y, double radius);
}
/** "ConcreteImplementor" 1/2 */
class DrawingAPI1 implements DrawingAPI {
public void drawCircle(double x, double y, double radius) {
System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
}
}
/** "ConcreteImplementor" 2/2 */
class DrawingAPI2 implements DrawingAPI {
public void drawCircle(double x, double y, double radius) {
System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius);
}
}
Programação Orientada a Objetos 2 91
Flávio de Oliveira Silva, M.Sc.
/** "Abstraction" */
18
10/6/2011
Bridge
Exemplo - Código
/** "Implementor" */
interface DrawingAPI {
public void drawCircle(double x, double y, double radius);
}
/** "ConcreteImplementor" 1/2 */
class DrawingAPI1 implements DrawingAPI {
public void drawCircle(double x, double y, double radius) {
System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
}
}
/** "ConcreteImplementor" 2/2 */
class DrawingAPI2 implements DrawingAPI {
public void drawCircle(double x, double y, double radius) {
System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius);
}
}
Bridge
Exemplo - Código
interface Shape {/** "Abstraction" */
public void draw(); // low-level
public void resizeByPercentage(double pct); // high-level
}
class CircleShape implements Shape {/** "Refined Abstraction" */
private double x, y, radius;
private DrawingAPI drawingAPI;
public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) {
this.x = x; this.y = y; this.radius = radius;
this.drawingAPI = drawingAPI;
}
public void draw() {// low level ii.e.
low-level e Implementation specific
drawingAPI.drawCircle(x, y, radius);
}
public void resizeByPercentage(double pct) {// high-level i.e. Abstraction specific
radius *= pct;
}
}
Programação Orientada a Objetos 2 93
Flávio de Oliveira Silva, M.Sc.
19
10/6/2011
Bridge
Exemplo - Código
/** "Client" */
class BridgePatternClient {
public static void main(String[] args) {
Shape[]
p [] shapes
p = new Shape[]p [] {
new CircleShape(1, 2, 3, new DrawingAPI1()),
new CircleShape(5, 7, 11, new DrawingAPI2()),
};
Composite
Objetivo
Compor objetos de forma que partes e estruturas, formadas por estas partes
possam ser tratadas de maneira uniforme
Motivação
Em muitas situações objetos podem ser compostos para gerar outros objetos
Caso o código trate as partes e os objetos compostos de forma diferenciada
acarretando em uma aplicação mais complexa
Uso
Representar hierarquias do tipo “todo-parte” de objetos
Tratar tanto objetos individuais, quanto composições destes objetos de
maneira uniforme
20
10/6/2011
Composite
Exemplo
O diagrama mostra o uso deste padrão de projeto
Um Menu é composto é composto de elementos MenuItem, porém o
tratamento do todo (Menu) como das suas partes (MenuItem) será mesmo
pois ambos representam herança de MenuComponent
class GOF-Composite
Client
MenuComponent
0..*
é composto
MenuItem Menu
{leaf}
Composite
Exempo
Aplicação Gráfica
Uma Ellipse ou um Circle é um elemento gráfico
É possível ter grupos de elementos gráficos que devem ser tratados de
maneira uniforme
class GOF-Composite Sample
«interface»
Client Graphic
21
10/6/2011
Composite
Exemplo – Código
import java.util.List;
import java.util.ArrayList;
interface Graphic {/** "Component" */
//Prints the graphic.
g p
public void print();
}
public final class Ellipse implements Graphic {/** "Leaf" */
public void print() {
System.out.println("Ellipse");
}
}
public final class Circle implements Graphic {/**
{/ "Leaf"
Leaf *//
public void print() {
System.out.println("Circle");
}
}
Composite
Exemplo – Código
class Group implements Graphic {/** "Composite" */
//Collection of child graphics.
private List<Graphic> mChildGraphics = new ArrayList<Graphic>();
public void p
p print()
() {
for (Graphic graphic : mChildGraphics) {
graphic.print();
}
}
public void add(Graphic graphic) {//Adds the graphic to the composition.
mChildGraphics.add(graphic);
}
public void remove(Graphic graphic) {//Removes the graphic from the composition.
composition
mChildGraphics.remove(graphic);
}
}
22
10/6/2011
Composite
Exemplo – Código
public class Client {/** Client */
public static void main(String[] args) {
Ellipse ellipse1 = new Ellipse(); //Initialize single graphics
Ellipse
p ellipse2
p = new Ellipse();
p ();
Circle circle1 = new Circle ();
Circle circle2 = new Circle ();
Group = new Group(); //Initialize three composite graphics
Group graphic1 = new Group();
Group graphic2 = new Group();
graphic1.add(ellipse1); //Composes the graphics
graphic1.add(ellipse2);
graphic1.add(circle1);
graphic1 add(circle1);
graphic2.add(circle2);
graphic.add(graphic1);
graphic.add(graphic2);
//Prints the complete graphic components
graphic.print();
}
}
Programação Orientada a Objetos 2 100
Flávio de Oliveira Silva, M.Sc.
Proxy
Objetivo
Fornece um substituto para um outro objeto permitindo o controle de acesso
a este objeto
Motivação
Em muitas situações é necessário controlar o acesso a um objeto a fim de
adiar o custo de sua criação e inicialização
Por exemplo:
Um documento que contém várias fotos. Abrir todos os arquivos de forma
simultânea poderia ser ineficiente
O proxy fornece uma representação para a imagem e sua exibição somente
ocorrerá no momento em que a página que contiver a respectiva foto seja exibida
Uso
Proxy Remoto – Oferece uma representação local para um objeto remoto, por
exemplo, em outro espaço de endereçamento
Proxy Virtual – Oferece uma representação para um objeto cuja criação será
feita por demanda
Protection Proxy – Controla o acesso a um determinado objeto
Programação Orientada a Objetos 2 101
Flávio de Oliveira Silva, M.Sc.
23
10/6/2011
Proxy
Estrutura
A classe ProxySubject representa a classe Subject. Neste caso o cliente (Client)
utilizará uma instância de ProxySubject e não de subject
A classe ProxySubject pode por exemplo: restringir o acesso ao subject; ser uma
representação local; conter um cache para um subject remoto
class GOF-Proxy
Client «interface»
ISubj ect
+ operation() : void
+ operation() : void
Proxy
Exemplo
A classe ProxyImage representa uma imagem
Neste caso trata-se de um proxy virtual, o cliente do proxy (ProxyClient) não
precisa criar objetos da classe RealImage, mas apenas da classe ProxyClient
que representará um objeto da classe RealImage
class GOF-Proxy
«interface»
ProxyClient Image
+ displayImage() : void
+ main(String[]) : void
ProxyImage RealImage
24
10/6/2011
Proxy
Exemplo – Código
interface Image {
void displayImage();
}
Proxy
Exemplo – Código
class ProxyImage implements Image {
private String filename;
private RealImage image;
public ProxyImage(String
p y g ( g filename)) {
this.filename = filename;
}
public void displayImage() {
if (image == null) {
image = new RealImage(filename);
}
image.displayImage();
}
}
25
10/6/2011
Proxy
Exemplo – Código
class ProxyClient {
public static void main(String[] args) {
Image image1 = new ProxyImage("HiRes_10MB_Photo1");
Imageg image2g = new ProxyImage("HiRes
y g ( _10MB_Photo2");
);
Padrões Comportamentais
Representam e descrevem padrões de comunicação entre objetos a fim de
realizar um comportamento específico
Seu objetivo é que foco do projeto seja a interconexão entre os objetos a fim de
obter este comportamento
Padrões definidos por Gamma et. al. (GoF)
Chain of Responsibility
Command
Flyweigth
Interpreter
Iterator
Mediator
Memento
Observer
State
Strategy
Template
Visitor
26
10/6/2011
Padrões Comportamentais
Observer
Command
Strategy
Template
Iterator
Visitor
Mediator
Observer
Objetivo
Define uma dependência entre objeto e vários outros(um-para-muitos) sendo
que em uma alteração neste objeto, todos os outros são notificados
Motivação
Em muitas situações um objeto pode ter vários outros dependentes.
Neste caso sempre que este objeto (sujeito) for alterado é interessante que
outros sejam notificados
Isto porém pode levar a um forte acoplamento entre os mesmos
Uso
Quando uma abstração (Classe) possuir dois ou mais aspectos estes podem
ser encapsulados em diferentes classes
Em situações onde a alteração de um objeto pode afetar um grupo de outros
objetos não conhecidos previamente
Permitir que um objeto seja capaz de notificar outros sem que estejam
acoplados
27
10/6/2011
Observer
Estrutura
O sujeito (subject) é observado por uma lista de observadores (Observer)
Um método notify() invoca o método update() nos observadores
class GOF-Observ er
Subject Observer
+ attach(Observer) : void
+ detach(Observer) : void
+ notfiy() : void
Observer
Exemplo
A medida que as ações de uma empresa (Stock) forem alteradas os
investirores (Inverstor) serão notificados
class GOF-Observ er
Stock
- symbol: String
- price: double «interface»
- investors: List<IInvestor> = new List<IInves...
IInvestor
+ Stock(String, double) + update(Stock) : void
+ attach(IInvestor) : void
+ detach(IInvestor) : void
+ notify() : void
+ getPrice() : double
+ setPrice(double) : void -stock
+ getSymbol() : String
M i A li ti
MainApplication Petrobras
Inv estor
+ Main() : void + Petrobras(String, double)
- name: String
- stock: Stock
+ Investor(String)
+ update(Stock) : void
+ getStock() : Stock
+ setStock(Stock) : void
28
10/6/2011
Observer
Exemplo - Código
/// MainApp startup class for Real-World
public class MainApplication {
public static void Main(){
// Create Petrobras stock and attach investors
Petrobras petro = new Petrobras("Petrobras", 120.00);
petro.attach(new Investor("Sorros"));
petro.attach(new Investor("Berkshire"));
Observer
Exemplo - Código
/// The 'Subject' abstract class
public abstract class Stock {
private String symbol; private double price;
private List<IInvestor> investors = new List<IInvestor>();
p ();
public Stock(String symbol, double price){
this.symbol = symbol;
this.price = price;
}
public void attach(IInvestor investor){ investors.add(investor); }
public void detach(IInvestor investor){ investors.remove(investor); }
public void notify() {
for (IInvestor investor : investors){
investor.update(this); }
System.out.println("");
}
29
10/6/2011
Observer
Exemplo - Código
public double getPrice(){ return price; }
public void setPrice(double nprice){
if (price != nprice){
price = nprice;
p p ;
notify();
}
}
// Gets the symbol
public String getSymbol(){
return symbol;
}
Observer
Exemplo - Código
// The 'ConcreteSubject' class
public class Petrobras extends Stock
{
// Constructor
public Petrobras(String symbol, double price) {
super(symbol, price)
}
}
30
10/6/2011
Observer
Exemplo - Código
// The 'Observer' interface
interface Iinvestor {
void update(Stock stock);
}
Command
Objetivo
Motivação
Uso
Estrutura
Exemplo Código
31
10/6/2011
Command
Exemplo - Estrutura
class GOF-Command
-flipUpCommand
«interface»
Command
- + execute() : void
flipDownCommand
Sw itch
PressSw itch - flipUpCommand: Command
- flipDownCommand: Command
+ main(String[]) : void
+ Switch(Command, Command)
+ flipUp() : void
+ flipDown() : void
FlipUpCommand
-theLight-theLight
Light
+ Light()
+ turnOn() : void
+ turnOff() : void
Command
Código
/* The Invoker class */
public class Switch {
private Command flipUpCommand;
private Command flipDownCommand;
p p ;
public Switch(Command flipUpCmd, Command flipDownCmd) {
this.flipUpCommand = flipUpCmd;
this.flipDownCommand = flipDownCmd;
}
public void flipUp() {
flipUpCommand.execute();
}
32
10/6/2011
Command
Código
/* The Receiver class */
public class Light {
public Light() { }
public void turnOn()
p () {
System.out.println("The light is on");
}
public void turnOff() {
System.out.println("The light is off");
}
}
Command
Código
/* The Command interface */
public interface Command {
void execute();
}
/* The Command for turning the light on in North America, or turning the light off in most other
places */
public class FlipUpCommand implements Command {
private Light theLight;
public FlipUpCommand(Light light) {
this.theLight = light;
}
public void execute(){
theLight.turnOn();
}
}
33
10/6/2011
Command
Código
/* The Command for turning the light off in North America, or turning the light on in most other
places */
public class FlipDownCommand implements Command {
Command
Código
public class PressSwitch { // The test class or client
public static void main(String[] args) {
Light lamp = new Light();
Command switchUp p = new FlipUpCommand(lamp);
p p ( p);
Command switchDown = new FlipDownCommand(lamp);
Switch s = new Switch(switchUp, switchDown);
try {
if (args[0].equalsIgnoreCase("ON")) {
s.flipUp();
} else if (args[0].equalsIgnoreCase("OFF")) {
s.flipDown();
} else {
System.out.println("Argument \"ON\" or \"OFF\" is required.");
}
} catch (Exception e) {
System.out.println("Arguments required.");
}
}
}
Programação Orientada a Objetos 2 123
Flávio de Oliveira Silva, M.Sc.
34
10/6/2011
Command
Código
/* The Invoker class */
public class Switch {
Strategy
Objetivo
Definir uma família de algoritmos que podem ser intercambiáveis sendo possível alterar
os algoritmos sem alterar o cliente que os utiliza
Motivação
ç
Considere a existência de vários algoritmos para uma mesma tarefa, por exemplo,
ordenar uma lista de objetos
Uma aplicação que deve suportar diferentes algoritmos pode tornar-se complexa e no
geral não permite a adição de novos que possam ser desenvolvidos
Uso
Configurar o uso considerando que existem classes relacionadas com diferentes
comportamentos
Existência de diferentes algoritmos ou métodos que podem ser implementados e que
devem ser selecionados em tempo de execução
Impedir que o cliente tenha que manter dados específicos para diferentes algoritmos
Remover o uso de estruturas de seleção, como um switch, em uma operação. Neste
caso cada possibilidade de código a ser executado se transforma em uma diferente
estratégia
35
10/6/2011
Strategy
Estrutura
Um mesma mesma estratégia (Strategy) pode ser implementada de diversas
formas (AConcreteStategy, BConcreteStategy, CConcreteStategy)
Em um contexto (Context) contém uma estratégia genérica
(Client) Uma alteração no contexto pode
O contexto é utlizado por um cliente (Client).
indicar o uso de uma nova estratégia
class GOF-Strategy
Context «interface»
Strategy
- strategy: Strategy
+ callAlgorithm() : void
Client
Strategy
Exemplo
Neste caso a estratégia permite que o cliente (StrategyExample) utilize
diferentes operações aritméticas conforme o contexto (Context) utilizado
class GOF
GOF-Strategy
Strategy Sample
«interface»
Context
-strategy Strategy
- strategy: Strategy
+ execute(int, int) : int
+ Context(Strategy)
+ executeStrategy(int, int) : int
StrategyExample + execute(int, int) : int + execute(int, int) : int + execute(int, int) : int
+ main(String[]) : void
36
10/6/2011
Strategy
Exemplo - Código
interface Strategy {
int execute(int a, int b);
}
class ConcreteStrategyAdd
gy implements
p Strategy
gy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyAdd's execute()");
return a + b; }
}
class ConcreteStrategySubtract implements Strategy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategySubtract's execute()");
return a - b; }
}
class ConcreteStrategyMultiply implements Strategy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyMultiply's execute()");
return a * b; }
}
Programação Orientada a Objetos 2 128
Flávio de Oliveira Silva, M.Sc.
Strategy
Exemplo - Código
class Context {
private Strategy strategy;
// Constructor
public Context(Strategy
p ( gy strategy)
gy) {
this.strategy = strategy; }
public int executeStrategy(int a, int b) {
return strategy.execute(a, b); }
}
class StrategyExample {
public static void main(String[] args) {
Context context;
context = new Context(new ConcreteStrategyAdd());
int resultA = context.executeStrategy(3,4);
context = new Context(new ConcreteStrategySubtract());
int resultB = context.executeStrategy(3,4);
context = new Context(new ConcreteStrategyMultiply());
int resultC = context.executeStrategy(3,4);
}
}
Programação Orientada a Objetos 2 129
Flávio de Oliveira Silva, M.Sc.
37
10/6/2011
Template
Objetivo
Define um modelo (template) de um algoritmo em deixando alguns passos
para suas subclasses
Motivação
Uso
Implementar as partes invariantes de um algoritmo na superclasse, deixando
para a subclasse o comportamento que pode variar
Evitar a duplicação de código, localizado o comportamento comum na
superclasse
Estrutura
Exemplo
E Código
l Códi
Template
Estrutura
A classe abstrata (AbstractClass) possui um conjunto de operações e um
método (templateMethod) que é responsável por invocar as operaçoes
que são especializadas nas subclasses (ConcreteClass1 e
ConcreteClass2)
class GOF-Template
templateMethod(){
AbstractClass ...
baseOperation();
+ templateMethod() : void ...
+ baseOperation() : void primitiveOperation1();
+ primitiveOperation1() : void ...
+ primitiveOperation2() : void primitiveOperation2();
}
ConcreteClass1 ConcreteClass2
38
10/6/2011
Template
Exemplo
Um jogo contém operações básicas que serão especializadas
O template method aqui é playOneGame()
class GOF
GOF-Template
Template
Game
# playersCount: int
+ initializeGame() : void
+ makePlay(int) : void
+ endOfGame() : boolean
+ printWinner() : void
+ playOneGame(int) : void
Monopoly Chess
Template
Exemplo – Código
public abstract class Game {
protected int playersCount;
public abstract void initializeGame();
public abstract void makePlay(int
p y( p player);
y );
public abstract boolean endOfGame();
public abstract void printWinner();
/* A template method : */
public final void playOneGame(int playersCount) {
this.playersCount = playersCount;
initializeGame();
int j = 0;
while (!endOfGame()) {
makePlay(j);
j = (j + 1) % playersCount;
}
printWinner();
}
}
Programação Orientada a Objetos 2 133
Flávio de Oliveira Silva, M.Sc.
39
10/6/2011
Template
Exemplo – Código
//Now we can extend this to implement other games
public class Monopoly extends Game {
/* Implementation of necessary concrete methods */
public void initializeGame()
p () {
// Initialize players
// Initialize money
}
public void makePlay(int player) {
// Process one turn of player
}
public boolean endOfGame() {
// Return true if game is over
// according to Monopoly rules
}
public void printWinner() {
// Display who won
}
}
Programação Orientada a Objetos 2 134
Flávio de Oliveira Silva, M.Sc.
Template
Exemplo – Código
public class Chess extends Game {
/* Implementation of necessary concrete methods */
public void initializeGame() {
// Initialize players
p y
// Put the pieces on the board
}
public void makePlay(int player) {
// Process a turn for the player
}
public boolean endOfGame() {
// Return true if in Checkmate or
// Stalemate has been reached
}
public void printWinner() {
// Display the winning player
}
}
40
10/6/2011
Template
Exemplo – Código
public class Monopoly extends Game {
/* Implementation of necessary concrete methods */
public void initializeGame() {
// Initialize players
p y
// Initialize money
}
public void makePlay(int player) {
// Process one turn of player
}
public boolean endOfGame() {
// Return true if game is over
// according to Monopoly rules
}
public void printWinner() {
// Display who won
}
}
Iterator
Objetivo
Fornece uma maneira de acessar os componentes de um objeto sem expor a
sua representação interna
Motivação
Uso
Estrutura
Exemplo Código
41
10/6/2011
Iterator
Estrutura
O iterator (ListIterator) permite o acesso ao objeto da lista em que seja
necessário conhecer o seu interior
Iterator
Exemplo
Em uma televisão (ConcreteTV) existe um Iterator (ChannelIterator) sobre os canais desta
televisão
Idepentende de como o acesso aos canais é feito é possível obtê-los através do Iterator
class GOF-Iterator
«interface»
Iterator
ChannelIterator
+ hasNext() : boolean
«interface» - channels: List<String> + next() : void
- currentPos: int = 0 + currentItem() : String
TV
+ getIterator() : ChannelIterator + ChannelIterator(List<String>)
+ hasNext() : boolean
+ next() : void
+ currentItem() : String
-iterator
ConcreteTV
- iterator: ChannelIterator
- channels: List<String>
+ ConcreteTV()
+ getIterator() : ChannelIterator
42
10/6/2011
Iterator
Código
//Iterator interface
public interface Iterator {
public boolean hasNext();
public void next();
p ();
public String currentItem();
//Aggregate interface
public interface TV {
public ChannelIterator getIterator();
//other TV methods
}
Iterator
Código
//Concrete Aggregator
public class ConcreteTV implements TV{
private ChannelIterator iterator;
private List<String>
p g channels;;
public ConcreteTV() {
iterator = new ConcreteChannelIterator(channels);
}
43
10/6/2011
Iterator
Código
//Concrete Iterator
public class ChannelIterator implements Iterator {
private List<String> channels;
private int currentPos = 0;;
p
public ChannelIterator(List<String> channels){
this.channels = channels;
}
public boolean hasNext(){
if(currentPos + 1 < channels.size()){
return true;
}
return false;
}
public void next() { currentPos++; }
Visitor
Objetivo
Permite que uma ou mais operações seja aplicada a um conjunto ou estrutura de
objetos, desacoplando as operações desta estrutura
A operação
p ç “visita” o conjunto
j de objetos
j e é executada sobre o mesmo
Motivação
Para calcular o total de uma compra, diferentes operações devem ser executadas
sobre o produto. Em alguns caso é necessário pesar o produto para obter seu preço,
em outros é necessário apenas ler seu código de barras, em outro finalmente é
aplicado um desconto por compras em quantidade
Ao passar no caixa, o atendente será o Visitor, que irá obter um produto e então
calculará o seu preço.
Uso
Desacoplar a lógica de uma operação dos objetos que são submetidos a esta o
operação
Permitir que operações diferentes e não relacionadas seja aplicadas em uma estrutura
de objetos
44
10/6/2011
Visitor
Estrutura
A interface Visitor define uma operação sobre um elemento (ConcreteElement).
Um elemento por sua vez possui uma operação que permite aceitar um visitante
(accept), associando-se ao vistante
Visitor
Estrutura
45
10/6/2011
Visitor
Estrutura
Visitor
Exemplo
Utilizando um visitor (PostageVisitor) será possível implementar o cálculo do frente para
diferentes produtos (Book, CD, DVD) e então calcular o valor do frete (calculatePostage)
class GOF - Visitor
ShoppingCart
- items: ArrayList<Visitable>
+ calculatePostage() : double
PostageVisitor
«interface» «interface»
Visitable - totalPostageForCart: double Visitor
+ accept(Visitor) : void + visit(Book) : void + visit(Book) : void
+ visit(CD) : void + visit(CD) : void
+ visit(DVD) : void + visit(DVD) : void
+ getT otalPostage() : double
Element
+ accept(Visitor) : void
Book
+ getPrice() : double
+ getWeight() : double
46
10/6/2011
Visitor
Exemplo - Código
//Element interface
public interface Visitable {
public void accept(Visitor visitor);
}
//abstract element
public abstract class Element implements Visitable {
//accept the visitor
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
//concrete element
public class CD extends Element{
}
//concrete element
public class DVD extends Element{
}
Visitor
Exemplo - Código
//concrete element
public class Book extends Element {
private double price;
private double weight;
p g ;
47
10/6/2011
Visitor
Exemplo - Código
public interface Visitor {
public void visit(Book book);
//visit other concrete items
public void visit(CD
p ( cd);
);
public void visit(DVD dvd);
}
Visitor
Exemplo - Código
public class PostageVisitor implements Visitor {
private double totalPostageForCart;
//collect data about the book
public void visit(Book
p ( book)) {
//assume we have a calculation here related to weight and price
//free postage for a book over 10
if(book.getPrice() < 10.0) {
totalPostageForCart += book.getWeight() * 2;
}
}
//add other visitors here
public void visit(CD cd){
cd){...}}
public void visit(DVD dvd){...}
//return the internal state
public double getTotalPostage() {
return totalPostageForCart;
}
}
Programação Orientada a Objetos 2 151
Flávio de Oliveira Silva, M.Sc.
48
10/6/2011
Visitor
Exemplo - Código
public class ShoppingCart {
//normal shopping cart stuff
private ArrayList<Visitable> items;
public double calculatePostage()
p g () {
//create a visitor
PostageVisitor visitor = new PostageVisitor();
//iterate through all items
for(Visitable item: items) {
item.accept(visitor);
}
double postage = visitor.getTotalPostage();
return postage;
}
}
Mediator
Objetivo
Permite criar um baixo acoplamento entre um conjunto de objetos que se
comunica e interage
O mediator é o objeto que realiza a comunicação com cada objeto permitindo
que esta comunicação entre estes objetos ocorra de forma independende
uma das outras
Motivação
Uma torre de controle em um aeroporto é o mediator entre os aviões e o
aeroporto
Ao invés dos aviões comunicarem entre si cada um comunica diretamente
com a torre
Uso
Quando existe uma comunicação complexa, porém bem definida, entre
objetos
Em situações onde existem vários relacionamentos entres objetos produzindo
uma diagrama de classes que indica alto acoplamento
49
10/6/2011
Mediator
Estrutura
O mediator define uma interface para a comunicação entre diferentes
partes (Colleage). Um mediator é então criado (ConcreteMediator) a fim
de implementar o comportamento para a comunicação
Mediator
Exemplo
A comunicação entre as entidades (FixedEntity e MobileEntity) é realizada
através do mediator (ApplicationMediator) associado a cada entidade
class GOF - Mediator
«interface» Entity
Mediator - mediator: Mediator
+ send(String, Entity) : void
-mediator + Entity(Mediator)
+ send(String) : void
+ getMediator() : Mediator
+ receive(String) : void
Client ApplicationMediator
MobileEntity
- entitys: ArrayList<Entity>
+ main(String[]) : void + receive(String) : void
FixedEntity
+ ApplicationMediator()
pp ()
+ addEntity(Entity) : void
+ receive(String) : void
+ send(String, Entity) : void
50
10/6/2011
Mediator
Código
//Mediator interface
public interface Mediator {
public void send(String message, Entity entity);
}
public abstract class Entity {//Entity Abstract Base Class
private Mediator mediator;
public Entity(Mediator m){
mediator = m;
}
public void send(String message){ //send a message via the mediator
mediator.send(message, this);
}
public Mediator getMediator(){ //get access to the mediator
return mediator;
}
public abstract void receive(String message);
}
Programação Orientada a Objetos 2 156
Flávio de Oliveira Silva, M.Sc.
Mediator
Código
public class ApplicationMediator implements Mediator {
private ArrayList<Entity> entitys;
public ApplicationMediator(){
entitys
y = new ArrayList<Entity>();
y y ();
}
public void addEntity(Entity entity) {
entitys.add(entity);
}
public void send(String message, Entity originator) {
//let all other screens know that this screen has changed
for(Entity entity: entitys){
//don
//don'tt tell ourselves
if(entity != originator){
entity.receive(message);
}
}
}
}
Programação Orientada a Objetos 2 157
Flávio de Oliveira Silva, M.Sc.
51
10/6/2011
Mediator
Código
public class FixedEntity extends Entity {
public void receive(String message){
System.out.println("FixedEntity Received: " + message);
}
}
Mediator
Código
//Client shows the use
public class Client {
public static void main(String[] args) {
ApplicationMediator
pp mediator = new ApplicationMediator();
pp ();
mediator.addEntity(desktop);
mediator.addEntity(mobile);
}
}
52