Sei sulla pagina 1di 257

Programao Modular em C++

Padres de Projeto
Roberto S. Bigonha 06 de novembro de 2008
Todos os direitos reservados Proibida a cpia sem autorizao do autor

@Roberto S. Bigonha Padres de Projeto C++

Padres GoF
Abstract Factory Adapter Builder Bridge Chain-of-Responsability Command Composite Decorator Factory Method Faade Flyweight Interpreter
@Roberto S. Bigonha Padres de Projeto

Iterator Mediator Memento Observer Prototype Proxy Strategy Singleton State Template Method Visitor

C++

Padres de Projeto
Projeto de sistemas OO uma atividade complexa e difcil Projetar software OO reusvel ainda mais difcil Projetistas experientes resam solues desenvolvidas em outros projetos Sistemas OO bem estruturados tm padres recorrentes de classes e objetos

@Roberto S. Bigonha

Padres de Projeto

C++

Padres de Projeto
So solues recorrentes para um problema em um dado contexto Capturam a experincia de desenvolvimento de software So arquiteturas comprovadas para construir software orientado por objetos flexvel e mais extensvel. Cada padro fornece uma soluo para um problema comum no projeto de software
@Roberto S. Bigonha Padres de Projeto C++ 4

Padres de Projeto - Motivao


Idias derivadas de trabalho cientfico do arquiteto Christopher Alexander Christopher Alexander estudou meios de melhorar o processo de projeto de edifcios e reas urbanas Projeto arquitetnico da construo civil usa elementos estabelecidos para o projeto de novas edificaes. Por exemplo: arcos e colunas so uma estratgia comprovada para construir edificaes seguras projeto e instalao de portas e janelas seguem um padro estabelecido
@Roberto S. Bigonha Padres de Projeto C++ 5

Padres de Projeto Benefcios


Estabelecem vocabulrio comum entre desenvolvedores Reduzem a complexidade do processo de projeto de software Aumentam confiabilidade do software via o uso de arquiteturas comprovadas e experincia acumulada Aumentam grau de reutilizao de software

@Roberto S. Bigonha

Padres de Projeto

C++

Histrico de Padres de Software


1987 Cunnigham e Beck usaram as idia de Alexander com Smalltalk 1990 A GoF (Gamma, Helm, Johnson e Vlissides) iniciou a compilao de um catlogo 1991 Pattern Workshop na OOSPLA (Bruce Anderson) 1994 Primeira conferncia em PLoP 1995 GoF publica livro Design Patterns
@Roberto S. Bigonha Padres de Projeto C++ 7

Livros de Padres de Projeto


Patterns: Elements of Reusable Objet-Oriented Software, Addison-Wesley, 1995 Richard P. Gabriel, Patterns of Software: Tales From the Software Community, Oxford University
Gamma, Helm, Johnson and Vlissides, Design

Press, 1996. Martin Fowler, Analysis Patterns: Reusable Object Models, Addison-Wesley, 1997. Alan Shalloway and James R. Trott, Design Patterns Explained, Addison-Wesley, 2001. Steven John Metsker, Design Patterns Java Worlbook, Addison-Wesley, 2001
@Roberto S. Bigonha Padres de Projeto C++ 8

Livros de Padres de Projeto


Floyd Marinescu, EJB Design Patterns: Advanced Patterns, Processes and Idioms, John Wiley, 2002 Alan Shalloway and James R. Trott, Design Patterns Explained, Addison-Wesley, 2001. Steven John Metsker, Design Patterns Java Worlbook, Addison-Wesley, 2001 Floyd Marinescu, EJB Design Patterns: Advanced Patterns, Processes and Idioms, John Wiley, 2002 Mark Grand, Patterns in Java, Volume 2, Wiley, 1999. Mark Grand, Java Enterprise Design Patterns Patterns in Java, Volume 3, Wiley, 2001
@Roberto S. Bigonha Padres de Projeto C++ 9

Livros de Padres de Projeto


Linda Rising (editor), The Patterns Handbook, Cambridge, University Press, 1998 James W. Cooper, Java Design Patterns A Tutorial, Addison- Wesley, 2000. Alan Shalloway and James R. Trott, Design Patterns Explained, Addison-Wesley, 2001. Steven John Metsker, Design Patterns Java Worlbook, Addison-Wesley, 2001 Floyd Marinescu, EJB Design Patterns: Advanced Patterns, Processes and Idioms, John Wiley, 2002

@Roberto S. Bigonha

Padres de Projeto

C++

10

Elementos Essenciais aos Padres


Nome do padro: usado para facilitar comunicao entre desenvolvedores Problema/motivao: quando usar o padro? Soluo: descrio das partes que fazem o padro relacionamentos, responsabilidades e colaboraes Consequncias: Ps, contra, reusabilidade, extensibilidade

@Roberto S. Bigonha

Padres de Projeto

C++

11

Categorias dos 23 Padres GoF


Padres de Criao Descrevem tcnicas para instanciar objetos: Singleton, Abstract Factory, Factory Method,
Prototype, Builder

Padres Estruturais Permitem organizar classes e objetos em estruturas maiores: Proxy, Adapter, Bridge, Composite,
Decorator, Faade, Flyweight

Padres Comportamentais Permitem atribuir responsabilidades a objetos:


Memento, State, Chain-of-Responsability, Command, Observer, Template Method, Iterator, Mediator, Interpreter, Visitor
@Roberto S. Bigonha Padres de Projeto C++ 12

Notao GoF (OMT)


conhecimento um muitos

ClasseAbstrata AssinaturasOps( )

criao agregao

ClasseConcreta operaes( ) atributos

itlico = interface, classe ou mtodo abstratos

SubClasseConcreta1 operaes( ) atributos

SubClasseConcreta2 operaes( ) atributos pseudocdigo

@Roberto S. Bigonha

Padres de Projeto

C++

13

Padres de Criao

@Roberto S. Bigonha

Padres de Projeto

C++

14

Tipos de Padres de Criao


Descrevem tcnicas comuns de se organizar classes e objetos em um sistema com facilidades para criar determinados objetos: Singleton Abstract Factory Factory Method Prototype Builder

@Roberto S. Bigonha

Padres de Projeto

C++

15

Padro Singleton

@Roberto S. Bigonha

Padres de Projeto

C++

16

Padro de Criao Singleton


Padro que garante que somente um objeto da classe poder ser instanciado Permite fcil acesso instncia nica Aplicao: Situaes em que somente deve haver um objeto que gerencia conexes com um banco de dados Recursos necessrios: construtor de classe privado campos e membros estticos

@Roberto S. Bigonha

Padres de Projeto

C++

17

Estrutura do Padro Singleton

Singleton

static Singleton& instance ( ) Operations() GetSingletonData () static uniqueInstance singletonData

return uniqueInstance

@Roberto S. Bigonha

Padres de Projeto

C++

18

Padro Singleton Soluo I

@Roberto S. Bigonha

Padres de Projeto

C++

19

Padro Singleton Soluo I


Permite-se somente uma nica instncia da classe Singleton A construtora privada: no permite que objetos da classe Singleton sejam criados via o operador new diretamente no permite que objetos de subclasses de Singleton sejam criados diretamente A implementao usa: um mtodo esttico para criar o objeto nico controle de visibilidade do construtor para restringir a criao de objetos
@Roberto S. Bigonha Padres de Projeto C++ 20

Padro Singleton I
class Singleton { static Singleton* theInstance; Singleton ( ) { } Singleton& operator=(Singleton&); Singleton(const Singleton&); public: static Singleton* instance( ); Operaes normais da classe, e.g., void f( ); }; Singleton* Singleton::theInstance = 0; Singleton* Singleton::instance( ){ if (theInstance==0) theInstance=new Singleton(); return theInstance; }
@Roberto S. Bigonha Padres de Projeto C++ 21

Padro Singleton I...


int main( ) { ... Singleton* s1 = Singleton::instance( ); Singleton* s2 = Singleton::instance( ); if (s1 != s2) cout << "No pode acontecer!"; else cout << "Funcionou!"; }

@Roberto S. Bigonha

Padres de Projeto

C++

22

Problemas
int main( ) { Singleton* s1 = Singleton::instance( ); Singleton* s2 = Singleton::instance( ); if (s1 != s2) cout << "No devia acontecer!"; else cout << "Funciona!"; delete s1; // ?????? s2->f( ); // Exceo!? }

Como evitar a possibilidade do delete?

@Roberto S. Bigonha

Padres de Projeto

C++

23

Padro Singleton Soluo II

@Roberto S. Bigonha

Padres de Projeto

C++

24

Padro Singleton II (sem delete)


class Singleton { static Singleton theInstance; Singleton ( ) { } Singleton& operator=(Singleton&); Singleton(const Singleton&); public: static Singleton& instance( ); Operaes normais da classe, e.g., f( ); }; Singleton Singleton::theInstance( ); Singleton& Singleton::instance( ){ return theInstance; }
@Roberto S. Bigonha Padres de Projeto C++ 25

Padro Singleton II (sem delete)...


int main( ) { ... Singleton& s1 = Singleton::instance( ); Singleton& s2 = Singleton::instance( ); if (s1 != s2) cout << "No devia acontecer!"; else cout << "Funcionou!"; s1.f( ); delete s1; // Erro de compilao s2.f( ); }

Agora no h como apagar objetos s1 ou s2

@Roberto S. Bigonha

Padres de Projeto

C++

26

Padro Singleton Soluo III (objetos de subclasses somente)

@Roberto S. Bigonha

Padres de Projeto

C++

27

Padro Singleton III


Deseja-se criar somente objetos de subclasse de Singleton A classe Singleton agora abstrata para evitar que dela sejam criados objetos diretamente O objeto nico da famlia Singleton a ser criado de uma das subclasses de Singleton Para garantir unicidade, objetos da subclasse devem ser criados apenas via a operao instance da superclasse Singleton Entretanto, objetos de subclasses de Singleton podem ser criados livre e diretamente via operador new e, assim, podem no ser nicos
@Roberto S. Bigonha Padres de Projeto C++ 28

Padro Singleton III ...


int main ( ) { const int MAX = 2; const string nome[MAX] = {mgico,std}; MazeFactory** x; x = new MazeFactory*[MAX]; for (int i = 0; i < MAX; i++) x[i] = MazeFactory::instance(nome[i]); }

Todos os elementos de x referenciam mesmo objeto No se sabe que subclasses sero instanciadas!
@Roberto S. Bigonha Padres de Projeto C++ 29

Padro Singleton III...


class MazeFactory { virtual void abstract( ) = 0; // impede objetos static MazeFactory* theInstance; protected: MazeFactory( ) { } // permite objetos de subclasses public: static MazeFactory* instance(string s); }; MazeFactory* MazeFactory::instance(string s){...} MazeFactory* MazeFactory::theInstance = 0;

Objetos desta classe no podem ser criados


@Roberto S. Bigonha Padres de Projeto C++ 30

Padro Singleton III...


class MagicFactory: public MazeFactory { void abstract( ) { } // Esta subclasse concreta public: MagicFactory( ) {... } Operaes definidas para a classe; }; class StdFactory: public MazeFactory{ void abstract( ) { } // Esta subclasse concreta public: StdFactory( ) {... } Operaes definidas para a classe; };

Objetos destas subclasses podem ser criados


@Roberto S. Bigonha Padres de Projeto C++ 31

Problemas
MazeFactory* MazeFactory::instance(string s) { if (theInstance == 0) { if (s == mgico) theInstance = new MagicFactory( ); else if (s == agent) theInstance = new StdFactory( ); else theInstance = new DefaultFactory( ); } return theInstance; }

Funciona, mas viola-se o princpio Open-Close!

@Roberto S. Bigonha

Padres de Projeto

C++

32

Mais Problemas
Construtoras das subclasses de MazeFactory so pblicas Pode-se, ento, criar diretamente mais de uma instncia de subclasses de MazeFactory:
void g( ) { ... MagicFactory* x = new MagicFactory( ); ... }

Como impedir esta possibilidade? Vide Soluo IV a seguir


@Roberto S. Bigonha Padres de Projeto C++ 33

Padro Singleton Soluo IV

@Roberto S. Bigonha

Padres de Projeto

C++

34

Padro Singleton Soluo IV


Possvel criao de objetos de subclasses da classe abstrata Singleton Operao instance de Singleton apenas retorna o objeto j criado Operao instance de cada subclasse de Singleton, cria somente cria uma instncia se nenhuma j foi criada Construtoras das subclasses de Singleton so declaradas private para evitar que delas sejam criados objetos diretamente Classe Singleton abstrata para evitar que dela sejam criados objetos diretamente
@Roberto S. Bigonha Padres de Projeto C++ 35

Padro Singleton Soluo IV ...


class MazeFactory { virtual void abstract( ) = 0; protected: static MazeFactory* theInstance; public: struct NullError { }; static MazeFactory* instance() throw(NullError); ... }; MazeFactory* MazeFactory::theInstance = 0; MazeFactory* MazeFactory::instance()throw(NullError){ if (theInstance) return theInstance; throw NullError( ); }

Objetos desta classe no podem ser criados


@Roberto S. Bigonha Padres de Projeto C++ 36

Padro Singleton Soluo IV...


class MagicFactory: public MazeFactory { void abstract( ) { } // classe concreta MagicFactory ( ) { } // objetos s locais ... public: static MazeFactory* instance( ) { if (theInstance == 0) theInstance = new MagicFactory( ); return theInstance; } ... };

Terceiros no podem criar objetos desta classe


@Roberto S. Bigonha Padres de Projeto C++ 37

Padro Singleton Soluo IV...


class StdFactory: public MazeFactory { void abstract( ) { } MagicFactory( ) { } ... public: static MazeFactory* instance( ) { if (theInstance == 0) theInstance = new StdFactory( ); return theInstance; } .... };

Terceiros no podem criar objetos desta classe


@Roberto S. Bigonha Padres de Projeto C++ 38

Padro Singleton Soluo IV...


void g( ) { MazeFactory* f = MagicFactory::instance( ); ... try{ MazeFactory* g = MazeFactory::instance( ); } catch(MazeFactory::NullError} {...} ... MazeFactory* h = StdFactory::instance( ); ... }

Somente um objeto de uma subclasse de cada vez!

@Roberto S. Bigonha

Padres de Projeto

C++

39

Padro Factory Method

@Roberto S. Bigonha

Padres de Projeto

C++

40

Padro de Criao Factory Method


Padro que define mtodos especializados para fabricao de objetos Os mtodos de fabricao pertencem classe que os utiliza para criar objetos Mtodos de fabricao de objetos podem livremente ser redefinidos para criar outros objetos As subclasses que redefinem os mtodos de fabricao, em geral, no so conhecidas durante o desenvolvimento Usa-se este padro quando no se sabe que tipo de objetos sero criados

@Roberto S. Bigonha

Padres de Projeto

C++

41

Estrutura de Factory Method


Factory factoryMethod( ) anOperation( )

Product

product = factoryMethod()

ConcreteProduct

AnotherFactory factoryMethod( )

return new ConcreteProduct( )

@Roberto S. Bigonha

Padres de Projeto

C++

42

Fabricao de Labirintos Sem Factory Methods

@Roberto S. Bigonha

Padres de Projeto

C++

43

Exemplo 1: Sem Factory Method


Classe MazeGame com o mtodo createMaze:
class MazeGame { public: Maze* createMaze( ) { Maze* maze = new Maze( ); Room* r1 = new Room(1); Room* r2 = new Room(2); Constri salas r1 e r2; maze->addRoom(r1); maze->addRoom(r2); return maze; } };
@Roberto S. Bigonha Padres de Projeto C++ 44

Construo das Salas r1 e r2


Door* door = new Door(r1,r2); r1->setside(NORTH, new Wall( ) ); r1->setside(South, new Wall( ) ); r1->setside(East, door ); r1->setside(West, new Wall( ) ); r2->setside(NORTH, new Wall( ) ); r2->setside(South, new Wall( ) ); r2->setside(East, new Wall( ) ); r2->setside(West, door );
@Roberto S. Bigonha Padres de Projeto C++ 45

Problemas
Mtodo createMaze muito inflexvel Se quisermos criar outro tipo de jogo de labirinto, com EnchantedRooms e EnchantedDoors, createMaze( ) dever ser modificado Como ento reprojetar createMaze de forma a tornar fcil a criao de outros jogos? Como tornar createMaze um mtodo fechado para modificaes (princpio OCP)? Soluo: adicionar Mtodos de Fabricao MazeGame.

@Roberto S. Bigonha

Padres de Projeto

C++

46

Fabricao de Labirintos Usando Factory Methods

@Roberto S. Bigonha

Padres de Projeto

C++

47

Exemplo 2: Usando Factory Method


class MazeGame { public: virtual Maze* makeMaze( ){return new Maze();} virtual Room* makeRoom(int n){return new Room(n);} virtual Wall* makeWall( ){return new Wall();} virtual Door*makeDoor(Room* r1,Room* r2) { return new Door(r1,r2); } Maze* createMaze( ); };

@Roberto S. Bigonha

Padres de Projeto

C++

48

Exemplo 2: Uando Factory Method


Maze* MazeGame::createMaze ( Maze* maze = makeMaze( ); Room* r1 Room* r2 = makeRoom(1); = makeRoom(2); ) {

Constri salas r1 r2; maze->addRoom(r1); maze->addRoom(r2); return maze; }

@Roberto S. Bigonha

Padres de Projeto

C++

49

Constri Salas r1 e r2
Door* door = makeDoor(r1,r2); r1->setside(NORTH, r1->setside(SOUTH, r1->setside(EAST, r1->setside(WEST, r2->setside(NORTH, r2->setside(SOUTH, r2->setside(EAST, r2->setside(WEST,
@Roberto S. Bigonha

makeWall( ) ); makeWall( ) ); door); makeWall( ) ); makeWall( ) ); makeWall( ) ); makeWall( ) ); door);


C++ 50

Padres de Projeto

Exemplo 2: Criando Outro Jogo


Para criao de um novo jogo, basta estender MazeGame, redefinindo os mtodos de fabricao:
class EnchantedMazeGame: public MazeGame { public: Room* makeRoom(int n) { return new EnchantedRoom(n); } Wall* makeWall( ){return new EnchantedWall( );} Door* makeDoor(Room* r1, Room* r2 ) { return new EnchantedDoor(r1,r2 );

} };
@Roberto S. Bigonha Padres de Projeto C++ 51

Vantagens do Factory Method


Mtodo createMaze adia a criao dos objetos do labirinto para suas subclasses Mtodo createMaze respeita OCP Os mtodos de fabricao, neste caso, so: makeRoom makeDoor makeWall Cdigo de createMaze, herdado pelas subclasses, agora mais flexvel e reusvel
@Roberto S. Bigonha Padres de Projeto C++ 52

Padro Abstract Factory

@Roberto S. Bigonha

Padres de Projeto

C++

53

Padro de Criao Abstract Factory


Os mtodos de fabricao so reunidos em uma classe separada, denominada Abstract Factory Objetos da classe Abstract Factory so fbricas com a responsabilidade de criao de objetos Uma fbrica cria o produto conforme a definio corrente de seus mtodos de fabricao. A classe cliente decide em tempo de execuo qual fbrica de objetos a ser usada Os mtodos de fabricao podem ser redefinidos via definio de subclasses da Abstract Factory

@Roberto S. Bigonha

Padres de Projeto

C++

54

Estrutura de Abstract Factory


Abstract Factory createProductA( ) createProductB( ) AbstractProductA
Client ProductA1 ProductA2

ConcreteFactory1 createProductA( ) createProductB()

ConcreteFactory2 createProductA( ) createProductB ( )

AbstractProductB

ProductB1

ProductB2

@Roberto S. Bigonha

Padres de Projeto

C++

55

Fabricao de Labirintos com Abstract Factory Exemplo 1

@Roberto S. Bigonha

Padres de Projeto

C++

56

Exemplo 1 com Abstract Factory


MazeFactory agrupa os mtodos de fabricao
class MazeFactory { public: virtual Maze* makeMaze( ) {return new Maze( ) ;} virtual Room* makeRoom(int n){return new Room(n);} virtual Wall* makeWall( ){return new Wall( );} virtual Door* makeDoor(Room* r1, Room* r2){ return new Door(r1,r2 ) ; } };

@Roberto S. Bigonha

Padres de Projeto

C++

57

Exemplo 1 com Abstract Factory


class MazeGame { public: Maze* createMaze(MazeFactory* factory ) { Maze* maze = factory->makeMaze ( ); Room* r1 Room* r2 = factory->makeRoom(1); = factory->makeRoom(2);

Constri salas r1 e r2; maze->addRoom(r1); return maze; } };


@Roberto S. Bigonha Padres de Projeto C++ 58

maze->addRoom(r2);

Constri Salas r1 e r2
Door* door = factory->makeDoor(r1,r2); r1->setside(NORTH, factory->makeWall( ) ); r1->setside(SOUTH, factory->makeWall( ) ); r1->setside(EAST, door ); r1->setside(WEST, factory->makeWall( ) ); r2->setside(NORTH, r2->setside(SOUTH, r2->setside(EAST, r2->setside(WEST, factory->makeWall( ) ); factory->makeWall( ) ); factory->makeWall( ) ); door );

@Roberto S. Bigonha

Padres de Projeto

C++

59

Uma Nova Fbrica


class MinosFactory: public MazeFactory { public: Maze* makeMaze( ){return new MinosMaze( );} Room* makeRoom(int n){ return new MinosRoom(n); } Wall* makeWall( ) { return new MinosWall( ); } };
@Roberto S. Bigonha Padres de Projeto C++ 60

Uma Nova Fbrica


int main( ) { MazeFactory* f1 MazeFactory* f2 = new MazeFactory( ); = new MinosFactory( );

MazeGame* g1 = new MazeGame( ); MazeGame* g2 = new MazeGame( ); g1->createMaze(f1); g2->createMaze(f2); }

@Roberto S. Bigonha

Padres de Projeto

C++

61

Observaes
Agora createMaze com Abstract Factory muito mais flexvel createMaze delega a responsabilidade de criao de objetos ao objeto de tipo MazeFactory Estrutura garante que somente objetos de uma famlia podem ser criados Novos tipos de produtos para a mesma fbrica demanda reprogramao Novas fbricas dentro da mesma hierarquia podem ser facilmente incorporadas

@Roberto S. Bigonha

Padres de Projeto

C++

62

Fbricas de Widgets Exemplo 2

@Roberto S. Bigonha

Padres de Projeto

C++

63

Fbricas de Widgets
Problema: Na construo de interfaces GUI, deseja-se criar Widgets, por exemplo, janelas, botes e barras de rolagem Solues: Soluo 1: usando mtodos de fabricao (no mostrada, fica para o aluno) Soluo 2: usando fbricas e herana Soluo 3: usando fbricas e composio
@Roberto S. Bigonha Padres de Projeto C++ 64

Estrutura da Widget Factory

@Roberto S. Bigonha

Padres de Projeto

C++

65

Soluo 2: Fbrica de Produtos


WidgetFactory uma interface ou classe abstrata Widgets so criados por mtodos de fabricao implementados por subclasses de WidgetFactory

class WidgetFactory { public: virtual Window createWindow( )= 0 ; virtual ScrollBar createScrollBar( )=0; virtual Button createButton( ) = 0; };
@Roberto S. Bigonha Padres de Projeto C++ 66

Soluo 2: Fbrica de Produtos


MotifWidgetFactory implementa a WidgetFactory para a plataforma Motif:
class MotifWidgetFactory: public WidgetFactory{ public: Window createWindow( ){ return new MotifWindow( ); } ScrollBar createScrollBar( ) { return new MotifScrollBar( ); } Button createButton( ) { return new MotifButton( ); } };
@Roberto S. Bigonha Padres de Projeto C++ 67

Soluao 2: Cdigo Tpico de Cliente


O cdigo do cliente independe da forma como a fbrica cria os produtos:
class Cliente { ...... // cria fbrica WidgetFactory* wf=new MotifWidgetFactory( ); // cria Button* // cria Window* ... };
@Roberto S. Bigonha

um boto motif b = wf->createButton( ); uma janela motif w = wf->createWindow( );

Padres de Projeto

C++

68

Soluo 3: Usando Composio


Classe WidgetFactory a classe de fabricao Classe WidgetFactory contm referncias para fbricas usadas para criar os produtos Os construtores de WidgetFactory ou de suas subclasses definem os valores iniciais destas referncias Mtodos especficos permitem mudar as fbricas a qualquer momento durante a execuo As fbricas correntemente armazenadas so usadas para criar os produtos

@Roberto S. Bigonha

Padres de Projeto

C++

69

Soluo 3: Criao de Produtos


class WidgetFactory { WindowFactory* windowfactory; ScrollBarFactory* scrollBarFactory; ButtonFactory* buttonFactory; public: WidgetFactory(WindowFactory* wf, ScrollBarFactory* sbf, ButtonFactory* bf) ; void setWindowFactory(WindowFactory* wf); void setScrollBarFactory(ScrollBarFactory* sbf); void setButtonFactory(ButtonFactory* bf); virtual void createWindow( ); virtual void createScrollBar( ); virtual void createButton( ); };
@Roberto S. Bigonha Padres de Projeto C++ 70

Soluo 3: Fbricas Iniciais


WidgetFactory::WidgetFactory( WindowFactory* wf, ScrollBarFactory* sbf, ButtonFactory* bf) { windowFactory = wf; scrollBarFactory = sbf; buttonFactory = bf; }

@Roberto S. Bigonha

Padres de Projeto

C++

71

Soluo 3: Redefinio de Fbrica


void WidgetFactory::setWindowFactory( WindowFactory* wf) { windowFactory = wf; } void WidgetFactory::setScrollBarFactory( ScrollBarFactory* sbf) { scrollBarFactory = sbf; } void WidgetFactory::setButtonFactory( ButtonFactory* bf) { buttonFactory = bf; }

@Roberto S. Bigonha

Padres de Projeto

C++

72

Soluo 3: Criao de Objetos


void WidgetFactory::createWindow( ) { windowFactory->createWindow(); } void WidgetFactory::createScrollBar( ) { scrollBarFactory->createScrollBar(); } void WidgetFactory::createButton( ) { buttonFactory->createButton(); }
@Roberto S. Bigonha Padres de Projeto C++ 73

Padres Estruturais

@Roberto S. Bigonha

Padres de Projeto

C++

74

Tipos de Padres Estruturais


Descrevem tcnicas comuns de se organizar classes e objetos em um sistema: Proxy Adapter Bridge Composite Decorator Faade Flyweight

@Roberto S. Bigonha

Padres de Projeto

C++

75

Padro Proxy

@Roberto S. Bigonha

Padres de Projeto

C++

76

Padro Estrutural Proxy


Padro que permite a um objeto, chamado Proxy, agir como um substituto de outro. Exemplos: Um objeto mvel deve deixar um outro em seu lugar para responder mensagens a ele dirigidas durante sua ausncia Indicador de percentual de carga de um arquivo durante uma operao de transferncia de arquivos

@Roberto S. Bigonha

Padres de Projeto

C++

77

Motivao do Padro Proxy


Proxy : uma pessoa autorizada a agir em nome de outra um agente ou substituto uma autoridade que age em nome de outra H situaes em que o cliente no quer referenciar um objeto diretamente, mas precisa interagir com ele indiretamente O Proxy age como intermedirio entre o cliente e o objeto

@Roberto S. Bigonha

Padres de Projeto

C++

78

Estrutura do Padro Proxy


Client

Subject request( )

RealSubject request( ) aClient subject

rs

Proxy request( ) aProxy rs

rs->request( )

aRealSubject

@Roberto S. Bigonha

Padres de Projeto

C++

79

Exemplo 1 Proxy de Sincronizao

@Roberto S. Bigonha

Padres de Projeto

C++

80

Exemplo 1: Proxy de Sincronizao


Uma biblioteca tem a class TheTable, que no permite acessos exclusivos individuais em nvel de linhas. No se dispe do cdigo fonte de TheTable Entretanto conhece-se a interface de TheTable Como acrescentar a possibilidade de acesso exclusivo por linha da tabela? Soluo: Padro Proxy

@Roberto S. Bigonha

Padres de Projeto

C++

81

Exemplo 1: Proxy de Sincronizao


Seja Table a interface implementada por TheTable:
class Table { public: virtual Object* getElementAt(int row, int col) = 0; virtual void setElementAt(Object* element, int row, int col) = 0; virtual int numberOfRows( ) = 0 ; };

@Roberto S. Bigonha

Padres de Projeto

C++

82

Exemplo 1: Proxy de Sincronizao ...


class TheTable : public Table { public: Object* getElementAt(int row,int col); void setElementAt(Object* element, int row, int col); int numberOfRows( );

};
@Roberto S. Bigonha Padres de Projeto C++ 83

Exemplo 1: Proxy de Sincronizao ...


int main ( ) { Table* t = new theTable(); int row, col, n; Objec* x, y; Proxy* p = new Proxy(t); ... // preenche tabela t, etc Object* x = p->getElementAt(row,col); ... p->setElementAt(y,row,col); ... n = p->numberOfRows( );

}
@Roberto S. Bigonha Padres de Projeto C++ 84

Exemplo 1: Proxy de Sincronizao


class Proxy: public Table { Table* realTable; pthread_mutex_t* locks; public: Proxy(Table* toLock); Object* getElementAt(int row,int col); void setElementAt(Object* element, int row, int col); int numberOfRows( ); };

Para ter a sincronizao desejada, deve-se usar a classe Proxy em vez de TheTable
@Roberto S. Bigonha Padres de Projeto C++ 85

Exemplo 1: Proxy de Sincronizao


Proxy::Proxy(Table* toLock){ int row; realTable = toLock; locks = new pthread_mutex_t[toLock->numberOfRow( )]; for(row=0;row<toLock->numberOfRows();row++) pthread_mutex_init(&locks[row],0 ); }

@Roberto S. Bigonha

Padres de Projeto

C++

86

Exemplo 1: Proxy de Sincronizao


Object* Proxy::getElementAt(int row,int col) { Object* x; pthread_mutex_lock(&locks[row]);

x = realTable->getElementAt(row,col);

pthread_mutex_unlock(&lock[row]); return x; }

@Roberto S. Bigonha

Padres de Projeto

C++

87

Exemplo 1: Proxy de Sincronizao


void Proxy:: setElementAt(Object* element, int row,int col){

pthread_mutex_lock(&locks[row]);
realTable->setElementAt(element,row,col);

pthread_mutex_unlock(&lock[row]);
}

@Roberto S. Bigonha

Padres de Projeto

C++

88

Proxy Copy-On-Write Exemplo 2

@Roberto S. Bigonha

Padres de Projeto

C++

89

Exemplo 2: Proxy Copy-On-Write


Problema: Seja uma grande coleo de objetos, como uma tabela hash, da qual se pode ler ou escrever, sem concorrncia, muitos valores em uma nica operao. Deseja-se que as operaes de leitura ou escrita possam ser feitas concorrentemente Como agregar estas facilidades a uma tabela HashTable j definida, sem modific-la?

@Roberto S. Bigonha

Padres de Projeto

C++

90

Exemplo 2: Proxy Copy-On-Write


Soluo 1: bloqueio de acesso para toda a coleo cliente requisita o bloqueio, faz seus acessos e s ento libera o bloqueio
void doFetches(HashTable* ht) { pthread_mutex_lock_t (&lock) ; "realiza os acessos usando ht; pthread_mutex_unlock(&lock); } }

Mas este mtodo pode bloquear toda a tabela por longo tempo, comprometendo performance
@Roberto S. Bigonha Padres de Projeto C++ 91

Exemplo 2: Proxy Copy-On-Write


Soluo 2: clonar a coleo antes das consultas o bloqueio de acesso feito somente durante a clonagem
void doFetches(HashTable* ht) { HashTable* copy =(HashTable)ht->clone( ) ; "realiza os acessos usando copy; }

Mas a clonagem pode bloquear toda a tabela por longo tempo, comprometendo performance
@Roberto S. Bigonha Padres de Projeto C++ 92

Exemplo 2: Proxy Copy-On-Write


Soluo 3: clonar a tabela hash somente quando algum cliente quiser modificar a coleo simultaneamente a consultas de outros clientes o bloqueio de acesso deve ser mnimo esta operao chamada cpia-na-escrita Os acessos para leitura so livres
void doFetches(Proxy* ht) { realiza os acessos usando ht; }

@Roberto S. Bigonha

Padres de Projeto

C++

93

Exemplo 3: Proxy Copy-On-Write


class HashTable { .... public: HashTable(); int size( ) ; Object* get(Object[] key, int n); void put(Key[] key,Object[] value,int n); };

@Roberto S. Bigonha

Padres de Projeto

C++

94

Exemplo 3: Proxy Copy-On-Write


class Proxy: public HashTable { HashTable* theHashTable; pthread_mutex_t lockReader; pthread_mutex_t lockWriter public: Proxy(HashTable* t); int size ( ); Object* get(Object[] key, int n); void put(Key[] key,Object[] value,int n); };

@Roberto S. Bigonha

Padres de Projeto

C++

95

Exemplo 3: Proxy Copy-On-Write


Proxy::Proxy(HashTable* t) { theHashTable = t; pthread_mutex_init(&lockReader,0 ); pthread_mutex_init(&lockWriter,0 ); } int Proxy::size ( ) { return theHashTable->size( ); }

@Roberto S. Bigonha

Padres de Projeto

C++

96

Exemplo 3: Proxy Copy-On-Write


Object* Proxy::get(Object[ ] key,int n){ HashTable* t; pthread_mutex_lock(&lockReader); t = theHashTable; pthread_mutex_unlock(&lockReader); Object* v = t->get(key,n); return v; }

@Roberto S. Bigonha

Padres de Projeto

C++

97

Exemplo 3:Proxy Copy-On-Write


void Proxy::put(Object[] key, Object[] value,int n){ HashTable* copy = new HashTable( );

pthread_mutex_lock(&lockWrite) ;
*copy = *theHashTable; copy->put(key, value, n);

pthread_mutex_unlock(&lockReader); theHashTable = copy; pthread_mutex_unlock(&lockReader); pthread_mutex_unlock(&lockWrite);


}
@Roberto S. Bigonha Padres de Projeto C++ 98

Padro Adapter

@Roberto S. Bigonha

Padres de Projeto

C++

99

Motivao do Padro Adapter


Muitas vezes uma ferramenta ou uma classe de biblioteca no pode ser usada, porque sua interface no a requerida pela aplicao No se pode mudar a interface, porque no se dispe do cdigo fonte Mesmo que se pudesse, no interessante mudar a biblioteca a cada aplicao Padro Adapter fornece um objeto com uma nova interface que se adapta interface de outro objeto, permitindo a colaborao Anlogo a adaptadores de tomadas eltricas
@Roberto S. Bigonha Padres de Projeto C++ 100

Estrutura do Padro Adapter


Adaptador via composio (unidirecional)
client

Target request( )

Adaptee specificRequest( )

Adapter request( )

adaptee adaptee->specificRequest()

@Roberto S. Bigonha

Padres de Projeto

C++

101

Estrutura do Padro Adapter


Adaptador via herana mltipla (bidirecional)

client

Target Request ( )

Adaptee specificRequest( )

Adapter request( )

specificRequest( )

@Roberto S. Bigonha

Padres de Projeto

C++

102

Jogo de Pinos

@Roberto S. Bigonha

Padres de Projeto

C++

103

Jogo de Pinos
O clssico jogo de pinos redondos e quadrados que devem ser encaixados em um tabuleiro Suponha inicialmente que somente haja uma classe para cada tipo de pino: classe SquarePeg classe RoundPeg Seja PegBoard o tabuleiro de pinos quadrados Deseja-se inserir ambos os tipos de pinos da mesma forma

@Roberto S. Bigonha

Padres de Projeto

C++

104

Adaptador Unidirecional

@Roberto S. Bigonha

Padres de Projeto

C++

105

Exemplo 1: Adaptao Unidirecional


class PegBoard { string name; public: PegBoard(string name){this->name = name;} insertInSquareHole(SquarePeg* p){ p->insertS(name); } insertInRoundHole(RoundPeg* p){ p->insertR(name); } };
@Roberto S. Bigonha Padres de Projeto C++ 106

Exemplo 1: Adaptao Unidirecional


class SquarePeg { public: void insertS(string s ) { printf(Pino quadrado no board %s + s); } }; class RoundPeg { public: void insertR(string s ) { printf(Pino redondo no board %s + s); } };
@Roberto S. Bigonha Padres de Projeto C++ 107

Exemplo 1: Adaptao Unidirecional


Adaptadora de pinos quadrados
class Adapter: public SquarePeg { RoundPeg* rp; public: Adapter(RoundPeg* peg){ this->rp = peg; } void insertS(string s){ rp->insertR(string s); } };
@Roberto S. Bigonha Padres de Projeto C++ 108

Exemplo 1: Adaptao Unidirecional


int main( ) { PegBoard b = new BoardPeg(My Toy); SquarePeg* sp = new SquarePeg( ); b.insertInSquareHole(sp); RoundPeg* rp = RoundPeg( ): SquarePeg* adapted = new Adapter(rp); if (...) b.insertInSquareHole(adapted); else b.insertInRoundHole(rp); }

@Roberto S. Bigonha

Padres de Projeto

C++

109

Adaptador Bidirecional

@Roberto S. Bigonha

Padres de Projeto

C++

110

Exemplo 2: Adaptao Bidirecional


Note que no Exemplo 1 PegAdapter adapta um RoundPeg como um SquarePeg Problema: permitir que SquarePeg tambm possam ser adaptado para ser RoundPeg Uma soluo usar herana mltipla

@Roberto S. Bigonha

Padres de Projeto

C++

111

Exemplo 2: Adaptao Bidirecional


class RoundPeg { public: virtual void insertR(string s) = 0; }; class SquarePeg { public: void insertS(string s) = 0; };

@Roberto S. Bigonha

Padres de Projeto

C++

112

Exemplo 2: Adaptao Bidirecional


class PegBoard { String name; public: PegBoard(string name){this->name = name;} insertInSquareHole(SquarePeg* p){ p->insertS(name); } insertInRoundHole(RoundPeg* p){ p->insertR(name); } };
@Roberto S. Bigonha Padres de Projeto C++ 113

Exemplo 2: Adaptao Bidirecional


class ASquarePeg: public SquarePeg { public: void insertS(string s) { printf(Pino quadrado no board %s + s); } }; class ARoundPeg: public RoundPeg { public: void insertR(string s) { printf(Pino redondo no board %s + s); } };
@Roberto S. Bigonha Padres de Projeto C++ 114

Exemplo 2: Adaptao Bidirecional


public class Adapter: public SquarePeg, public RoundPeg { RoundPeg* rp; SquarePeg* sp; public: Adapter(SquarePeg* p) { sp = p; } Adapter(RoundPeg* p) { rp = p; } public void insertS(string s){ rp->insertR(s); } public void insertR(string s){ sp->insertS(s); } };
@Roberto S. Bigonha Padres de Projeto C++ 115

Exemplo 2: Adaptao Bidirecional


int main( ) { PegBoard b = new PegBoard(My Toy); SquarePeg* sp = new ASquarePeg( ); b.insertInSquareHole(sp); RoundPeg* rp = new ARoundPeg( ); b.insertInRoundHole(rp); SquarePeg* adaptedRound = new Adapter(rp); b.insertInSquareHole(adaptedRound); RoundPeg* adaptedSquare = new Adapter(sp); b.insertInRoundHole(adaptedRound); }

@Roberto S. Bigonha

Padres de Projeto

C++

116

Padro Composite

@Roberto S. Bigonha

Padres de Projeto

C++

117

Padro Estrutural Composite


Compe objetos em uma estrutura de rvore, representando uma hierarquia todo-parte Este processo chama-se composio recursiva Clientes tratam objetos individuais e composio de objetos de forma uniforme Cada componente da estrutura hierrquica implementa a mesma interface ou estende a mesma superclasse Exemplo: componentes adicionados a um objeto Jpanel so descendentes de Container, assim o mtodo repaint opera com todos eles uniformemente
@Roberto S. Bigonha Padres de Projeto C++ 118

Estrutura do Padro Composite


Client

Component operation( ) add(Component*) remove(Component*) getChild(int)

Leaf operation( )

Composite operation( ) add(Component*) remove(Component*) getChild(int)

children for all g in children g->operation()

@Roberto S. Bigonha

Padres de Projeto

C++

119

Motivao do Padro Composite

@Roberto S. Bigonha

Padres de Projeto

C++

120

Motivao do Padro Composite...

@Roberto S. Bigonha

Padres de Projeto

C++

121

Questes de Implementao
O objeto composto conhece os objetos que o compem, isto , seus filhos Os filhos devem conhecer o componente pai? depende da aplicao Onde os mtodos de administrao dos filhos (add, remove, getChild) devem ser declarados? na classe Component : mais transparente na classe Composite: mais seguro

@Roberto S. Bigonha

Padres de Projeto

C++

122

Gerncia dos Filhos no Componente


Todos os componentes tratados da mesma forma Mas clientes de Component tm acesso direto aos filhos (inseguro)

@Roberto S. Bigonha

Padres de Projeto

C++

123

Gerncia dos Filhos no Composite


Gerncia dos filhos encapsulada no Composite Mas componentes folha e objeto composto tm diferentes interfaces (opaco)

@Roberto S. Bigonha

Padres de Projeto

C++

124

Mais Questes de Implementao


Quem deve ter a referncia para a lista de componentes do objeto composto: classe Componente (folha) ou classe Composite? melhor se na classe Composite para evitar desperdcio de espao em cada folha Lista de filhos deve ser ordenada? depende da aplicao Quem apaga componentes? Coletor de lixo cuida Qual a melhor estrutura para os componentes? depende da aplicao
@Roberto S. Bigonha Padres de Projeto C++ 125

Janelas

@Roberto S. Bigonha

Padres de Projeto

C++

126

Exemplo 1: Janelas
Um sistema GUI tem objetos janela (Window) que podem conter vrios componentes GUI (widgets), tais como botes, reas de texto, etc A janela pode tambm conter contineres widget, que contm outros widgets Soluo 1: cada widget tem uma interface prpria para atualizar a janela mtodo update de Window atualiza cada componente

@Roberto S. Bigonha

Padres de Projeto

C++

127

Soluo 1: Janelas
class Window { Button* buttons; TextArea* textAreas; Menu* menus; WidgetContainer* containers; public: ... void update( ) { .... for (int k = 0 ; k < buttonsLen; k++) buttons[k]->draw( ); for (int k = 0 ; k < menusLen; k++) menus[k]->refresh( ); for (int k = 0 ; k < containersLen; k++) containers[k]->updateWidgets( ); ... } ... };
@Roberto S. Bigonha Padres de Projeto C++ 128

Soluo 2: Janelas
Soluo 1 viola o Princpio do Aberto-Fechado: Se desejarmos adicionar um componente de um novo tipo, deveremos modificar o mtodo update Soluo 2: Programar com base na interface Todos widgets (Button, Menu, TextArea, etc) implementam a mesma interface Widget Mas ainda ser mantida diferena entre widget e containers de widgets
@Roberto S. Bigonha Padres de Projeto C++ 129

Soluo 2: Janela
public class Window { Widget* widgets; WidgetContainer* containers; public: ... void update( ) { ... for (int k = 0 ; k < widgetsLen; k++) widgets[k]->update( ); for (int k = 0 ; k < containersLen; k++) containers[k]->updateWidgets(); ... } ... };
@Roberto S. Bigonha Padres de Projeto C++ 130

Soluo 3 com Padro Composite


Agora widgets e contineres de widget implementam a mesma interface

@Roberto S. Bigonha

Padres de Projeto

C++

131

Soluo 3 com Padro Composite


Component pode ser classe concreta ou abstrata
class Component { ..... }; class Button: public Component { ... }; class Menu: public Component { ... }; ... class WidgetContainer: public Component { Component * components; ... };

@Roberto S. Bigonha

Padres de Projeto

C++

132

Soluo 3 com Padro Composite


class Window { Component* components; .... public: void update( ) {... for (int k = 0;k<componentsLen;k++) components[k]->update( ); ... } };

@Roberto S. Bigonha

Padres de Projeto

C++

133

Padro Decorator

@Roberto S. Bigonha

Padres de Projeto

C++

134

Padro Estrutural Decorator


Muitas vezes deseja-se adicionar responsabilidades a objetos individualmente e no a todos da classe Padro Decorator permite que um objeto assuma dinamicamente responsabilidades adicionais sem afetar outros objetos Exemplo: a = new A (new B( ) ); onde o objeto a assume as funcionalidades de B recebido como parmetro de sua construtora

@Roberto S. Bigonha

Padres de Projeto

C++

135

Motivao do Padro Decorator


Desejamos adicionar propriedades a objeto Pode ser feito via herana, mas perde-se flexibilidade Uso de composio mais adequado: decorador contm o objeto decorado decorador tem a interface do decorado decorador repassa ao decorado o pedido de servio e possivelmente adiciona aes

@Roberto S. Bigonha

Padres de Projeto

C++

136

Motivao do Padro Decorator

@Roberto S. Bigonha

Padres de Projeto

C++

137

Motivao
Decoradores so uma alternativa flexvel a especializao de classe til quando especializao for impraticvel devido: possibilidade de se gerar muitas extenses necessidade de se ter um grande nmero de subclasses para suportar as combinaes possveis

@Roberto S. Bigonha

Padres de Projeto

C++

138

Motivao - Exemplo
Suponha que se deseja adicionar bordas e barras de rolagem a um componente GUI H 3 tipos de bordas: Plain 3D Fancy H dois tipos de barras de rolagem: Horizontal Vertical Portanto h 15 combinaes possveis
@Roberto S. Bigonha Padres de Projeto C++ 139

Soluo com Especializao


As 15 subclasses necessrias so: 1. TextView-Horizontal 2. TextView-Vertical 3. TextView-Horizontal-Vertical 4. TextView-Plain-Horizontal 5. ... 15. TextView-Fancy-Horizontal-Vertical Problemas: Escalabilidade, adio de novos tipos de bordas, adio de outro tipo de propriedade
@Roberto S. Bigonha Padres de Projeto C++ 140

Soluo com Padro Decorator

@Roberto S. Bigonha

Padres de Projeto

C++

141

Soluo do Padro Decorator

Decorator envia os pedidos de servio aos componentes


@Roberto S. Bigonha Padres de Projeto C++ 142

Soluo com Padro Decorator


Classe TextView nada sabe sobre bordas e barras class Component { public: virtual void draw( ) = 0; };
class TextView: public Component { public: void draw( ) { cdigo para desenhar TextView puro; } };

@Roberto S. Bigonha

Padres de Projeto

C++

143

Soluo com Padro Decorator


Decorador com a mesma interface de Component Supondo apenas um componente:
class Decorator: public Component { Component* component; public: Decorator(Component* component) { this->component = component; } void draw( ){ component->draw( ); } };
@Roberto S. Bigonha Padres de Projeto C++ 144

Soluo com Padro Decorator


class FancyBorder: public Decorador { public: FancyBorder(Component* component): Decorator(component) { } void draw( ) { Decorator::draw( ); cdigo para desenhar bordas; } };
@Roberto S. Bigonha Padres de Projeto C++ 145

Soluo com Padro Decorator


class VerticalScrollbar: public Decorator { public: VerticalScrollbar(Component* component): Decorator(component) { } void draw( ) { Decorator::draw( ); cdigo para desenhar barra vertical; } };
@Roberto S. Bigonha Padres de Projeto C++ 146

Soluo com Padro Decorator


class HorzScrollbar: public Decorator{ public: HorzScrollbar (Component* component): Decorator(component) { } void draw( ) { Decorator::draw( ); cdigo para desenhar barra horizontal; } };
@Roberto S. Bigonha Padres de Projeto C++ 147

Soluo com Padro Decorator


int void main( ){

Component* x, bx, vsbx, hsvsbx;


x = new TextView( ); bx = new FancyBorder(x); vsbx = new VerticalScrolllbar(bx); hsvsbx = new HorzScrollbar(vsbx); x->draw( ); bx->draw( ); vsbx->draw( ); hsvsbx->draw( ); }
@Roberto S. Bigonha Padres de Projeto C++ 148

Estrutura de Decorator
Component operation( )

ConcreteComponent operation( )

Decorator

component component.operation()

operation( )

ConcreteDecoratorA operation( ) addedBehavior( )


@Roberto S. Bigonha

ConcreteDecoratorB operation( ) addedBehavior ( )


Padres de Projeto

super.operation( ); addedBehavior( )
C++ 149

Padro Faade

@Roberto S. Bigonha

Padres de Projeto

C++

150

Padro Estrutural Faade


Permite que um objeto -- chamado de fachada -fornea uma interface simples para um subsistema formado por um agregado de objetos A fachada assume o conjunto de responsabilidades do sistema Objeto cliente usa objeto fachada para ter acesso aos objetos por trs da fachada Complexidade da interface do subsistema fica encapsulada pela fachada Exemplo: pedal do acelerador fachada para o subsistema de acelerao do carro
@Roberto S. Bigonha Padres de Projeto C++ 151

Motivao do Padro Faade

@Roberto S. Bigonha

Padres de Projeto

C++

152

Estrutura do Padro Faade


Faade

@Roberto S. Bigonha

Padres de Projeto

C++

153

Exemplo do Padro Faade


Um Compilador

@Roberto S. Bigonha

Padres de Projeto

C++

154

Padres Comportamentais

@Roberto S. Bigonha

Padres de Projeto

C++

155

Tipos de Padres Comportamentais


Definem estratgias para modelar como objetos colaboram uns com os outros em um subsistema: Memento State Chain-of-Responsability Command Observer Strategy Template Method Iterator Mediator Interpreter Visitor

@Roberto S. Bigonha

Padres de Projeto

C++

156

Padro Memento

@Roberto S. Bigonha

Padres de Projeto

C++

157

Padro Comportamental Memento


Permite que um objeto armazene seu estado, de modo que possa ser restaurado para um dado estado anterior (operao desfazer) Oferece histrico dos estados do objeto Padro memento exige trs tipos de objetos: Objeto originador: cujo estado deve ser lembrado Objeto memento: o primeiro elemento da histria Objeto zelador: armazena o histrio, i.e., tem referncias para todos os mementos associados ao originador.

@Roberto S. Bigonha

Padres de Projeto

C++

158

Padro State

@Roberto S. Bigonha

Padres de Projeto

C++

159

Padro Comportamental State


Representa um dos vrios estados que um objeto pode ocupar Padro contm um objeto estado, que encapsula o estado de um objeto de contexto O objeto pode ento reagir em conformidade com o seu estado corrente Objetos estado tm as operaes do objeto original que dependem do estado Padro de projeto usa uma superclasse abstrata State que contm mtodos que descrevem comportamentos para cada um dos estados que um objeto chamado objeto contexto pode ocupar
@Roberto S. Bigonha Padres de Projeto C++ 160

Motivao do Padro State

TCPConnection opera conforme seu estado corrente Objetos State tm as mesmas operaes do Original
@Roberto S. Bigonha Padres de Projeto C++ 161

Estrutura do Padro State


Context request( )
state

State handle( )

State->handle()

ConcreteStateA handle ( )

ConcreteStateB handle( )

@Roberto S. Bigonha

Padres de Projeto

C++

162

Padro State

@Roberto S. Bigonha

Padres de Projeto

C++

163

Padro State

@Roberto S. Bigonha

Padres de Projeto

C++

164

Padro State

@Roberto S. Bigonha

Padres de Projeto

C++

165

Padro Chain-of-Responsability

@Roberto S. Bigonha

Padres de Projeto

C++

166

Padro Chain-of-Responsability
Permite determinar, durante a execuo, o objeto que ir tratar uma dada mensagem Mensagem enviada a um objeto que pode tratar a mensagem ou pass-la para o prximo na cadeia Exemplos: PABX com vrias linhas: a primeira linha disponvel faz o atendimento Help em interface grfica (clique no component): se h help para componente, ele exibido, seno exibe-se o help daquele que o contm helps organizados do mais especfico para o mais geral objeto que prov o help no conhecido daquele que inicia o pedido
@Roberto S. Bigonha Padres de Projeto C++ 167

Motivao do Chain-of-Responsability

Todo objeto da cadeia conhece seu sucessor Todos os objetos da cadeia devem ter mesma interface
@Roberto S. Bigonha Padres de Projeto C++ 168

Estrutura do Chain-of-Responsability
Client successor

Handler handleRequest()

ConcreteHandler1 handleRequest( ) aClient aHandler

ConcreteHandler2 handleRequest( )

aConcreteHandler sucessor
Padres de Projeto C++

aConcreteHandler sucessor
169

@Roberto S. Bigonha

Padro Command

@Roberto S. Bigonha

Padres de Projeto

C++

170

Padro Comportamental Command


Encapsula pedidos como um objeto Clientes dos pedidos no precisam conhecer a ao a ser executada para o pedido Command permite desacoplar o objeto que faz a invocao da operao do objeto que a realiza Padro encapsula um comando de modo a us-lo em diversos objetos Usa-se padro Command quando: deseja-se especificar, enfileirar e executar pedidos em diferentes momentos precisa-se implementar operaes desfazer
@Roberto S. Bigonha Padres de Projeto C++ 171

Estrutura do Padro Command


Command execute()

Client

Invoker

Receiver action( )

receiver

ConcreteCommand execute( ) state

receiver->action( )

Invoker = uma classe da ferramenta, e.g., menuItem Receiver= classe da aplicao que realiza a ao desejada
@Roberto S. Bigonha Padres de Projeto C++ 172

Colaborao do Padro Command

@Roberto S. Bigonha

Padres de Projeto

C++

173

Guardio de Tarefas (TaskMinder)

@Roberto S. Bigonha

Padres de Projeto

C++

174

Task Minder
Deseja-se implementar uma classe que periodicamente executa um ou mais mtodos de vrios objetos Por exemplo, deseja-se criar uma classe para fazer uma operao de backup a cada hora e uma verificao do status do disco a cada 10 minutos A classe no deve conhecer detalhes destas operaes Soluo: Desacoplar a classe que escalona as operaes da classe que realiza as operaes
@Roberto S. Bigonha Padres de Projeto C++ 175

Soluo com Padro Command

@Roberto S. Bigonha

Padres de Projeto

C++

176

Tasks
class Task { public: virtual void performTask( ) = 0; }; class BackUpTask: public Task { public: BackUpTask ( ) { } void performTask( ){...dispara ao da task...} }; class StatusTask: public Task { public: StatusTask ( ) { } void performTask( ){...dispara ao da task...} };
@Roberto S. Bigonha Padres de Projeto C++ 177

TaskEntry
class TaskEntry { Task* task; long lastDone; long interval; public: TaskEntry(Task* task, long interval); Task* getTask( ); void setTask(Task* task); long getInterval( ); long setInterval(long ri); long getLastDone( ); void setLastDone(long t); };
@Roberto S. Bigonha Padres de Projeto C++ 178

TaskEntry ...
TaskEntry::TaskEntry(Task*task,long interval){ this->task = task; this->interval = interval; this->lastdone = currentSystemTime( ); } Task* TaskEntry::getTask( ) {return task;} void TaskEntry::setTask(Task* task){ this->task = task; }

@Roberto S. Bigonha

Padres de Projeto

C++

179

TaskEntry ...
long TaskEntry::getInterval( ){ return interval; } long TaskEntry::setInterval(long ri){ this->interval= ri; } long TaskEntry::getLastDone( ){ return LastDone; } void TaskEntry:: setLastDone(long t){ lastDone = t; }
@Roberto S. Bigonha Padres de Projeto C++ 180

Cliente Define asTarefas


int main( ) { long intervalo1 = 300, intervalo2 = 700; long sleepInterval=500; int maxTasks = 100; TaskMinder* tm = new TaskMinder(sleepInterval,maxTasks); BackUpTask* backUp = new BackUpTask( ); tm->addTask(backUp, intervalo1); StatusTask* status = new StatusTask( ); tm->addTask(status, intervalo2); }
@Roberto S. Bigonha Padres de Projeto C++ 181

TaskMinder
class TaskMinder: { long sleepInterval; Vector<TaskEntry*> taskList; public: typedef Vector<TaskEntry*>::iterator Enum; TaskMinder(long sleepInterval,int maxTasks); void addTask(Task* task,long interval); long getSleepInterval( ); void setSleepInterval(long s); void* minder(void* unused); };

@Roberto S. Bigonha

Padres de Projeto

C++

182

TaskMinder ...
TaskMinder::TaskMinder(long sleepInterval, int maxTasks){ this->sleepInterval = sleepInterval; tasklist = new Vector<TaskEntry*>(maxTasks); create_and_start_thread(&minder); } long TaskMinder::getSleepInterval( ){ return sleepInterval; } void TaskMinder::setSleepInterval(long sleep){ sleepInterval = sleep; }
@Roberto S. Bigonha Padres de Projeto C++ 183

TaskMinder ...
void TaskMinder::addTask(Task* task, long interval) { long i = (interval > 0) ? interval : 0; TaskEntry* t = new TaskEntry(task,i); tasklist.addElement(t); }

@Roberto S. Bigonha

Padres de Projeto

C++

184

Task Minder Invoca Tarefas


void* TaskMinder::minder(void* unused){ while (true){ sleep(sleepInterval); long now = currentSystemTime( ); for(Enum e=taskList.begin( ); e!=tasklist.end( ); e++ ){ if(e->getLastDone()+e->getinterval()<now){ e->getTask( )->performTask( ); e->setLastDone(now); } } } }
@Roberto S. Bigonha Padres de Projeto C++ 185

Padro Observer

@Roberto S. Bigonha

Padres de Projeto

C++

186

Padro Comportamental Observer


Padro de um objeto (observado) que notifica diversos objetos observadores Define um relacionamento 1-para-n entre objetos tal que quando o estado de um objeto observado for modificado, todos seus observadores so notificados automaticamente O observado tem conhecimento de seus observadores Os observadores tm conhecimento do observado Observadores, quando notificados de mudanas no observado, devem solicitar ao observado as informaes que lhes interessam
@Roberto S. Bigonha Padres de Projeto C++ 187

Aplicaes do Padro Observer


Componentes GUI, por exemplo, usam este padro para processar eventos do usurio: tratador de eventos observa mudanas no estado de um componente GUI particular que esteja registrado junto ao componente para este fim Controlador de temperatura observado por diversos sistemas de informao de temperatura (Celsus, Fahreheit, etc) Conjunto de dados observados por diversos exibidores de informao baseada nestes dados

@Roberto S. Bigonha

Padres de Projeto

C++

188

Motivao do Padro Observer

@Roberto S. Bigonha

Padres de Projeto

C++

189

Estrutura do Padro Observer


Subject add(Observer*) remove(Observer*)
notify( ) observers for all q in observers q->update(this )

Observer update(Subject* )

ConcreteSubject getState( ) subjectState

subject

ConcreteObserver update(Subject* ) observerState

return subjectState
@Roberto S. Bigonha Padres de Projeto

observerState = subject->getState( )
C++ 190

A Famlia dos Observadores


class Observer { public: virtual void update(Subject* s) = 0; };

@Roberto S. Bigonha

Padres de Projeto

C++

191

A Famlia dos Observados


class Subject { List* observers = new LinkedList(); public: void addObserver(Observer* observer); void removeObserver(Observer* observer); protected: void notifyObservers( ); };

@Roberto S. Bigonha

Padres de Projeto

C++

192

A Famlia dos Observados


void Subject::addObserver(Observer* observer) { observers->add(observer); } void Subject::removeObserver(Observer* observer) { observers->remove(observer); } void Subject::notifyObservers( ) { Iterator* it = observers->iterator( ); while (it->hasNext( )) { Observer* obs =(Observer)it->next(); obs->update(this); } }
@Roberto S. Bigonha Padres de Projeto C++ 193

Observadores de Temperatura
Subject addObserver(Observer*) removeObserver(Observer*) notifyObservers( ) observers

Observer
update(Subject*) {abstract}

notifyObservers() { for all obs in observers obs->update(this); }

Temperature value: double getValue() setValue(double)


@Roberto S. Bigonha Padres de Projeto

CelsiusTermometer update(Subject*)

C++

194

Um Observado e Dois Observadores


int main( ) { Temperature* t = new Temperature(10); t->addObserver(new CelsiusTermometer()); t->addObserver(new FahrenheitTermometer()); t->setValue(100);//observado muda de estado } Sada: Celsius: 100.0 Fahrenheit: 212.0

@Roberto S. Bigonha

Padres de Projeto

C++

195

A Classe de Um Observado
class Temperature: public Subject { double value; public: Temperature(double v):value(v){ } double getValue() { return value; } void setValue(double value) { this->value = value; notifyObservers( ); } };
@Roberto S. Bigonha Padres de Projeto C++ 196

Um Observador
class CelsiusTermometer: public Observer { public: void update(Subject* s) { Temperature* t = dynamic_cast<Temperature*>(s); double value = t->getValue( ); printf("Celsius: %d", value); } };

@Roberto S. Bigonha

Padres de Projeto

C++

197

Outro Observador
class FahrenheitTermometer: public Observer{ public: void update(Subject* s){ Temperature* t = dynamic_cast<Temperature*>(s); double value = 1.8*t->getValue() + 32; printf(Fahrenheit: %d",value); } };

@Roberto S. Bigonha

Padres de Projeto

C++

198

Padro Strategy

@Roberto S. Bigonha

Padres de Projeto

C++

199

Padro Comportamental Strategy


Padro semelhante ao padro State, mas que contm um objeto estratgia, que encapsula um algoritmo, em vez de informaes de estado Diferentemente do objeto State, o objeto Strategy no tem a relao 1-1 com as operaes correspondentes do objeto original As operaes do Strategy pode ser chamada por qualquer operao do original

@Roberto S. Bigonha

Padres de Projeto

C++

200

Motivao do Padro Strategy


Definir uma famlia de algoritmos, encapsular cada um e torn-los intercambiveis sem afetar clientes

Compositor encapsula a estratgia


@Roberto S. Bigonha Padres de Projeto C++ 201

Aplicao do Padro Strategy


Usa-se padro Strategy sempre que: muitas classes relacionadas diferem apenas no comportamento precisa-se de diferentes variantes de um algoritmo um algoritmo usa dados que o cliente no deve conhecer uma classe define muitos comportamentos que ocorrem em condicionais de muitas sadas.

@Roberto S. Bigonha

Padres de Projeto

C++

202

Estrutura do Padro Strategy


Context contextInterface( ) strategy

Strategy algorithmInterface( )

ConcreteStrategyA algorithmInterface( )

ConcreteStrategyB algorithmInterface( )

ConcreteStrategyC algorithmInterface( )

@Roberto S. Bigonha

Padres de Projeto

C++

203

Exemplo 1: Mtodo de Ordenao


Uma classe deseja decidir em tempo de execuo que algoritmo usar para ordenar um arranjo

@Roberto S. Bigonha

Padres de Projeto

C++

204

SortStategy
class SortArray { SortStrategy* sortStrategy; public: SortArray(SortStrategy* s) { this->sortStrategy = s; } SetSortStrategy(SortStrategy* s) { this->sortStrategy = s; } virtual void sort(int a[]){ sortStrategy->sort(a); } };
@Roberto S. Bigonha Padres de Projeto C++ 205

SortStategy
class SortStrategy { public: sort(int a[ ]) = 0 }; class BubbleSort: public SortStrategy { public: sort(int a[ ]) { ... } }; class QuickSort : public SortStrategy { public: sort(int a[ ]) { ... } };
@Roberto S. Bigonha Padres de Projeto C++ 206

SortStategy
int main { BubbleSort* bs = new BubbleSort( ); QuickSort* qs = new QuickSort(); SortArray sa1(bs); SortArray sa2(qs); int a [ ] = {...}; int b [ ] = {...}; ...; sa1.setSortStrategy(qs); ... sa1.sort(a); sa2.sort(b); }
@Roberto S. Bigonha Padres de Projeto C++ 207

Exemplo 3: Validao de Dados


Um componente GUI precisa decidir em tempo de execuo que estratgia usar para validar a entrada fornecida pelo usurio

@Roberto S. Bigonha

Padres de Projeto

C++

208

Padro Template Method

@Roberto S. Bigonha

Padres de Projeto

C++

209

Padro Template Method


Define o esqueleto de um algoritmo (mtodo), deixando alguns de seus passos para subclasses Permite redefinir certos passos de um algoritmo sem mudar a estrutura do algoritmo anlogo ao padro Strategy, mas todos os objetos compartilham um nico algoritmo definido por uma superclasse

@Roberto S. Bigonha

Padres de Projeto

C++

210

Motivao do Padro Template Method


Considere:

OpenDocument( ) tem cdigo fixo e o Template Method


@Roberto S. Bigonha Padres de Projeto C++ 211

Motivao do Padro Template Method


Mtodo openDocument, que o mtodo template, fixa a ordem das operaes, que so redefinveis:
void openDocument(string name) { if (!canOpenDocument(name)){return;} Document* doc = doCreateDocument( ); if (doc != null) { docs->addDocument(doc); doc->open( ); doc->doRead( ); } }

@Roberto S. Bigonha

Padres de Projeto

C++

212

Estrutura do PadroTemplate Method


AbstractClass

primitiveOperation1( ) primitiveOperation2( )

templateMethod( )

primitiveOperation1( ) primitiveOperation2( )

ConcreteClass primitiveOperation1( ) primitiveOperation2( )

@Roberto S. Bigonha

Padres de Projeto

C++

213

Exemplo 1: Padro Template Method


Considere a seguinte classe:
class PlainTextDocument { ... public: void printPage(Page page) { printPlainTextHeader( ); printf("%s",page.body( )); printPlainTextFooter( ); } void printPlainTextHeader( ) { ... } void printPlainTextFooter( ) { ... } };
@Roberto S. Bigonha Padres de Projeto C++ 214

Exemplo 1: Padro Template Method


Suponha haja uma outra classe quase igual:
class HtmlTextDocument { ... public: void printPage(Page page) { printHtmlTextHeader( ); printf("%s",page.body( ) ); printHtmlTextFooter( ); } void printHtmlTextHeader( ) { ... } void printHtmlTextFooter( ) { ... } };
@Roberto S. Bigonha Padres de Projeto C++ 215

Exemplo 1: Padro Template Method


Os mtodos printPage de PlainTextDocument e de HtmlTextDocument tm a mesma estrutura Sempre que subclasses tm mtodos comuns, razovel pensar em fatorao, isto , transferi-los para a respectiva superclasse. O mtodo template printPage fica na superclasse Os mtodos para imprimir cabealhos e rodaps ficam nas subclasses
@Roberto S. Bigonha Padres de Projeto C++ 216

Exemplo 1: Padro Template Method


A superclasse TextDocument com o template:
class TextDocument { ... public: void printPage(Page page) { printTextHeader( ); printf("%s", page.body( )); printTextFooter( ); } virtual void printTextHeader( ) = 0; virtual void printTextFooter( ) = 0; };
@Roberto S. Bigonha Padres de Projeto C++ 217

Soluo: Padro Template Method


Classes PlainTextDocument e HtmlTextDocument:
class PlainTextDocument: public TextDocument{ public: void printTextHeader( ) { ... } void printTextFooter( ) { ... } ...... }; class HtmlTextDocument: public TextDocument{ void printTextlHeader( ) { ... } void printTextFooter( ) { ... } .... };
@Roberto S. Bigonha Padres de Projeto C++ 218

Padro Iterator

@Roberto S. Bigonha

Padres de Projeto

C++

219

Padro Comportamental Iterator


Objetos tm acesso a objetos individuais de qualquer estrutura de dados, sem conhecer seu comportamento ou como a estrutura est armazenada Iteradores so recursos para apresentar os elementos de um objeto do tipo container. Iteradores so TAD que implementam as operaes: void first( ) void next( ) Item currentItem( ) bool isdone( )
@Roberto S. Bigonha Padres de Projeto C++ 220

Motivao do Padro Iterator


Lista com iterador

Iterador deve ter acesso a representao do objeto continer do qual ele apresenta valores Neste caso, o Iterador uma classe friend do

continer
@Roberto S. Bigonha Padres de Projeto C++ 221

Estrutura do Padro Iterador


Agregate createIterator( ) Iterator first( ) next( ) isdone( ) currentItem( )

Client

ConcreteAgregate createIterator( )

ConcreteIterator

return new ConcreteIterator(this)


@Roberto S. Bigonha Padres de Projeto C++ 222

Agregados com Interao (sem padro Iterador)

@Roberto S. Bigonha

Padres de Projeto

C++

223

Estruturas com Interao


class IntSet { int max, index, last; int *s; public: IntSet(int m); ... void insert(int i){... s[last++] = i;...} ... void first( ); bool isDone( ); void next( ) throw(Error); int currentItem( ) ; };

@Roberto S. Bigonha

Padres de Projeto

C++

224

Estruturas com Interao


IntSet::IntSet(int m):index(0),last(-1){ if (m<1)m=1; s=new int[max]; max=m; } void IntSet::insert(int i){... last++;...} void IntSet::first( ){index = 0;} bool IntSet::isDone( ) {return index >= last;} void IntSet::next( ) throw(Error){ if (!isDone) ++index; else throw Error( ); } int IntSet::currentItem( ) throw(Error){ if (!isDone) return s[index]; throw Error( ); }
@Roberto S. Bigonha Padres de Projeto C++ 225

Estruturas com Interao ...


class Error{ };

int main( ) { IntSet s = IntSet(1000); for (int i = 0; i <= 100 , i++) { s.insert(i); } try{ for (s.first( ); !s.isDone( ); s.next( ) ) { printf( "%d ", s.currentItem()); } } catch(Error){ ... } }
@Roberto S. Bigonha Padres de Projeto C++ 226

Padro Iterator Exemplo I

@Roberto S. Bigonha

Padres de Projeto

C++

227

Padro Iterador I
class IntSet { int max, *s, incr, last; public: IntSet(int m); friend class Iterator; void insert(int x); void remove(int x); int cardinalidade( ); bool in(int x); Iterator createIterator( ); };

@Roberto S. Bigonha

Padres de Projeto

C++

228

Padro Iterador I ...


IntSet::IntSet(int m):last(-1), incr(20) { if(m<1) m = 1; max = m; s = new int[max]; } void IntSet::insert(int x) { if (last == max-1) { int* t = new int[max+incr]; for (int i=0; i<max; i++) t[i] = s[i]; s = t; max += incr; } s[++last] = x; }

@Roberto S. Bigonha

Padres de Projeto

C++

229

Padro Iterador I ...


void IntSet::remove(int x) { ... } void IntSet::cardinalidade(int x) { ... } bool IntSet::in(int x) { ... } Iterator IntSet::createIterator( ){ return Iterador(this); }

@Roberto S. Bigonha

Padres de Projeto

C++

230

Padro Iterador I ...


class IntSet::Iterator { int index; IntSet* is; public: Iterator(IntSet* is); class Error { } void first( ); void next( ) throw(Error); bool isDone( ); int currentItem throw(Error); };

@Roberto S. Bigonha

Padres de Projeto

C++

231

Padro Iterador I
IntSet::Iterator::Iterator(IntSet* is):index(0){ this->is=is; }; void IntSet::Iterator::first( ) {index = 0;} void IntSet::Iterator::next( ) throw(Error){ if (index < is->max1) ++index; else throw Error(); } bool IntSet::Iterator::isDone( ) { return index == is->last; } int IntSet::Iterator::currentItem( ) { if (!isDone) return is->s[next]; throw Error(); }
@Roberto S. Bigonha Padres de Projeto C++ 232

Padro Iterador I
int main(String[ ] args) { IntSet s = IntSet(1000); IntSet::Iterador a = s.createIterador( ); IntSet::Iterador b = s.createIterador( ); for(int i=1; i<100 ; i++) {s.insert(i);} for(a.first( );!a.isDone( ); a.next( )){ int i = a.currentItem( ); for(b.first();!b.isDone );b.next( )){

int k = b.currentItem( );

if ((k%i) == 0) printf(%d divide %d,i,k); } } }


@Roberto S. Bigonha Padres de Projeto C++ 233

Padro Iterator Exemplo II

@Roberto S. Bigonha

Padres de Projeto

C++

234

Padro Iterador II
template <class Item> class List { public: List(long size=1000); long count( ) const; Item& get(long index) const; ... }; template <class Item> class Iterator { public: virtual void first( ) = 0; virtual void next( ) = 0; virtual bool isDone( ) const = 0; virtual Item currentItem( ) const = 0; protected: Iterator( ); };
@Roberto S. Bigonha Padres de Projeto C++ 235

Padro Iterador II ...


template <class Item> class ListIterator: public Iterator { const List<Item>* thelist; long current; public: ListIterator(const List<Item>* aList); virtual void first( ) ; virtual void next( ) ; virtual bool isDone( ) const ; virtual Item currentItem( ) const; };

@Roberto S. Bigonha

Padres de Projeto

C++

236

Padro Iterador II ...


template <class Item> ListIterator<Item>::ListIterator( const List<Item>* aList): theList(aList), current(0) { } template <class Item> void ListIterator<Item>::first( ){ current = 0; } template <class Item> void ListIterator<Item>::next( ){ current++; }
@Roberto S. Bigonha Padres de Projeto C++ 237

Padro Iterador II ...


template <class Item> bool ListIterator<Item>::isDone( ) const { return current >= thelist->count(); } template <class Item> Item ListIterator<Item>::currentItem() const { if (IsDone( )) throw IteratorOutOfBounds; return theList->get(current); }

@Roberto S. Bigonha

Padres de Projeto

C++

238

Padro Iterador II ...


class Employee {... void print( ){ ... } }; int main( ) { Employee* e; List<Employee*> cadastro(50); ListIterator<Employee*> it(&cadastro); comandos para preencher o cadastro; for (it.first(); !it.IsDone(); it.next()){ it.currentItem( )->print(); } }
@Roberto S. Bigonha Padres de Projeto C++ 239

Padro Iterator Polimrfico Exemplo III

@Roberto S. Bigonha

Padres de Projeto

C++

240

Motivaao do Padro Iterator Polimrfico


Iterador Polimrfico

@Roberto S. Bigonha

Padres de Projeto

C++

241

Padro Iterador III


template <class Item> class Iterator { public: virtual virtual virtual virtual

void void bool Item

first( ) = 0; next( ) = 0; isDone( ) const = 0; currentItem( ) const = 0;

protected: Iterator( ); };

@Roberto S. Bigonha

Padres de Projeto

C++

242

Padro Iterador III ...


template <class Item> class ListIterator: public Iterator { const List<Item>* thelist; long current; public: ListIterator(const List<Item>* aList); virtual void first( ) ; virtual void next( ) ; virtual bool isDone( ) const ; virtual Item currentItem( ) const; };

@Roberto S. Bigonha

Padres de Projeto

C++

243

Padro Iterador III ...


template <class Item> ListIterator<Item>::ListIterator( const List<Item>* aList): theList(aList), current(0) { } template <class Item> void ListIterator<Item>::first( ){ current = 0; } template <class Item> void ListIterator<Item>::next( ){ current++; }
@Roberto S. Bigonha Padres de Projeto C++ 244

Padro Iterador III ...


template <class Item> bool ListIterator<Item>::isDone( ) const { return current >= thelist->count(); } template <class Item> Item ListIterator<Item>::currentItem() const { if (IsDone( )) throw IteratorOutOfBounds; return theList->get(current); }

@Roberto S. Bigonha

Padres de Projeto

C++

245

Padro Iterador III ...


template <class Item> class AbstractList { public: virtual Iterator<Item>* createIterator() const = 0; ... };

@Roberto S. Bigonha

Padres de Projeto

C++

246

Padro Iterador III ...


template <class Item> class List: public AbstractList { public: List(long size=1000); long count( ) const; Item& get(long index) const; ... Iterator<Item>* createIterator( ) const { return new ListIterator<Item>(this); } };
@Roberto S. Bigonha Padres de Projeto C++ 247

Padro Iterador III ...


class Employee {... void print( ){ ... } }; int main( ) { Employee* e; AbstractList<Employee*>* cadastro; ... Iterator<Employee*>* it = cadastro->createIterator( ); comandos para preencher o cadastro; for(it->first();!it->IsDone();it->next()){ it->currentItem( )->print(); } delete it; // no esquecer! }
@Roberto S. Bigonha Padres de Projeto C++ 248

Padro Mediator

@Roberto S. Bigonha

Padres de Projeto

C++

249

Padro Comportamental Mediator


Define um objeto que encapsula como um conjunto de objetos que interagem Mediators provm fraco acoplamento entre objetos impedindo que eles interajam diretamente A interao entre os objetos pode ser modificada facilmente

@Roberto S. Bigonha

Padres de Projeto

C++

250

Padro Visitor

@Roberto S. Bigonha

Padres de Projeto

C++

251

Padro Comportamental Visitor


Representa uma operao que pode ser executado em um elemento da estrutura de um objeto Visitor permite que se defina uma nova operao sem mudar a classe dos elementos sobre os quais ela aplicvel Visitor permite que as aes de visita sejam encapsuladas em um nico mdulo
@Roberto S. Bigonha Padres de Projeto C++ 252

Motivao do Padro Visitor

@Roberto S. Bigonha

Padres de Projeto

C++

253

Estrutura do Padro Visitor

@Roberto S. Bigonha

Padres de Projeto

C++

254

Ao nos Elementos de Coleo


class A: public Z { .... public:void action( ) { ao de A; } }; class B: public Z { .... public:void action( ) { ao de B; } };

class Z {public: virtual void action( ) = 0;};


int main( ) { Z* c = {new A( ),new B( ), ...,new A( ), ... }; for (int i=0; i<lengthOfc; i++) c[i]->action( ); }
@Roberto S. Bigonha Padres de Projeto C++ 255

Padro Visitor
class A:public z{...}; class B:public z{...};

class Z { public: void accept (Visitor* v) {v->visit(this);} };


int main( ) { Z * c ={new A(),new B(), ...}; Visitor* v = new Visitor( ); .... for(int i=0; i<lengthOfc;i++) c[i]->accept(v); } ... }
@Roberto S. Bigonha Padres de Projeto

class Visitor { public: void visit(A* a){ ao de A; } void visit(B* b){ ao de B; } };


C++ 256

fim

@Roberto S. Bigonha

Padres de Projeto

C++

257

Potrebbero piacerti anche