Está en la página 1de 137

Patrones de Diseo

Tema 7

Grupo 46 TACC II Curso 2008/09 1

Indice
z Introduccin. I t d i
{ Patrones. { Descripcin de los Patrones. { Ejemplo: Patrones en el MVC de Smalltalk. { El catlogo de patrones.
z z z z z Patrones de Creacin. Patrones Estructurales. Patrones de Comportamiento. C Conclusiones. l i Bibliografa.
2

Introduccin
z Di Diseo especfico fi para el l problema, bl pero general l como para poder adecuarse a futuros requisitos y problemas. z Evitar el rediseo en la medida de lo posible. z Evitar resolver cada problema partiendo de cero. z Reutilizar soluciones que han sido tiles en el pasado. z Patrones recurrentes de clases y comunicacin entre objetos en muchas soluciones de diseo.
3

Patrn
z Un esquema que se usa para solucionar un problema problema. z El esquema ha sido probado extensivamente, y ha funcionado. Se tiene experiencia sobre su uso. z Existen E i t en muchos h d dominios: i i
{ { { { Novelas y el cine: hroe trgico, comedia romntica, etc. Arte. Ingenieras. Arquitectura.
z Christopher p Alexander. A Pattern Language: g g Towns, , Buildings, g , Construction. 1977. z http://www.patternlanguage.com

Patrones de Diseo
z R Reutilizar tili di diseos abstractos b t t que no i incluyan l d detalles t ll de la implementacin. z Un patrn es una descripcin del problema y la esencia de su solucin, q que se p puede reutilizar en casos distintos. z Es E una solucin l i adecuada d d a un problema bl comn. z A Asociado i d a orientacin i t i a objetos, bj t pero el l principio i i i general es aplicable a todos los enfoques de diseo software.
5

Patrones de Diseo
z Documentar D t l la experiencia i i en el l di diseo, en forma de un catlogo de patrones. z Categoras de patrones:
{ De creacin: implica el proceso de instanciar objetos. { Estructurales: composicin de objetos. { De comportamiento: cmo se com comunican nican los objetos objetos, cooperan y distribuyen las responsabilidades para lograr sus objetivos.
6

Patrones de Diseo
Estructura de un patrn
z Nombre N b del d l patrn. t
{ Describe el problema de diseo, junto con sus soluciones y consecuencias. { Vocabulario V b l i d de di diseo.

z Problema.
{ Describe cundo aplicar el patrn. { Explica el problema y su contexto.

z Solucin.
{ Elementos que forman el diseo, relaciones, responsabilidades. { No un diseo concreto, sino una plantilla que puede aplicarse en muchas situaciones distintas.

z Consecuencias. Consecuencias
{ Resultados, ventajas e inconvenientes de aplicar el patrn. { P.ej.: relacin entre eficiencia en espacio y tiempo; cuestiones de implementacin etc implementacin, etc.
7

Patrones de Diseo
Ejemplo: MVC de Smalltalk

z Modelo/Vista/Controlador.
40
D A

A X Y
B

B 20 25 10

C 15 15 20

D 5 20 60

30 20 10 0 A B C D

60 40 10

Modelo
A: B: C C: D: 40% 25% 15% 20%

Patrones de Diseo
Ejemplo: MVC de Smalltalk zS Separar l los objetos bj t con l los d datos t ( (modelo), d l ) sus visualizaciones (vistas) y el modo en que la interfaz reacciona ante la entrada al usuario (controlador). ( ) z Separar p estos componentes, p p para aumentar la flexibilidad y reutilizacin. zD Desacoplar l vistas i d de modelos, d l mediante di un protocolo l d de subscripcin/notificacin. z Cada vez que cambian los datos del modelo, avisar a que dependen p de l. Estas se actualizan. las vistas q
9

Patrones de Diseo
Ejemplo: MVC de Smalltalk z Patrn Observer, ms general (dependencias entre objetos). z Las vistas se pueden anidar: Vistas compuestas y simples.
{ Generalizacin: Patrn Composite.

z La relacin entre la vista y el controlador: patrn St t Strategy ( objeto (un bj t que representa t un algoritmo). l it ) z Otros patrones:
{ Factory Method: especifica la clase controlador predeterminada para una vista. { Decorator: Aade capacidad de desplazamiento a una vista vista.
10

El catlogo de patrones
Propsito
Creacin Estructurales
Adapter (de clases)

De Comportamiento
Interpreter. Template Method. Method

Clase

Factory Method

m mbito

Objeto j

Abstract Factory Builder Prototype Singleton

Adapter (de objetos). Bridge. Composite. Decorator. Facade. Flyweight. Proxy.

Chain of Responsibility. Command. Iterator. Mediator. Memento. Observer. State. Strategy. 11 Visitor.

El catlogo de patrones
Relaciones entre los patrones.

12

Indice
z Introduccin. Introduccin

z Patrones de Creacin.
{ Singleton. Singleton { Abstract Factory. { Factory Method. Patrones Estructurales. Patrones de Comportamiento. Concl siones Conclusiones. Bibliografa.

z z z z

13

Patrones de Creacin
z Ab Abstraen t el l proceso de d instanciacin i t i i z Ayudan a que el sistema sea independiente de cmo se crean crean, componen y representan los objetos. z Flexibilizan:
{ { { { qu se crea quin lo crea cmo se crea cundo se crea

z Permiten configurar un sistema:


{ estticamente (compile-time) { dinmicamente (run-time) ( )
14

Singleton
z Intencin. I t i
{ Asegurar que una clase tiene una nica instancia y proporciona un punto de acceso global a dicha instancia.

z Motivacin.
{ Hay veces que es importante asegurar que una clase tenga una sola instancia instancia, por ejemplo:
z z z z Un gestor de ventanas Una nica cola de impresin Un nico sistema de ficheros Un nico fichero de log, o un nico repositorio.

{ Cmo asegurarlo? una variable global hace el objeto accesible pero se puede instanciar varias veces accesible, veces. { Responsabilidad de la clase misma: actuar sobre el mensaje de creacin de instancias
15

Singleton
z Aplicabilidad.
{ Cuando debe haber una sola instancia, y debe ser accesible a los clientes desde un punto de acceso conocido. { Cuando la nica instancia debe ser extensible mediante subclasificacin, y los clientes deben ser capaces de usar una instancia extendida sin modificar su cdigo. cdigo

z Estructura.
Singleton static Singleton uniqueInstance singletonData static Singleton Instance () SingletonOperation () GetSingletonData () return uniqueInstance

16

Singleton
z Participantes: p
{ Singleton:
z Define una operacin de clase, llamada Instance que deja a los clientes acceder a la nica instancia. z Puede ser responsable de crear su nica instancia.

z Colaboraciones:
{ Los clientes acceden a la instancia de un Singleton a travs de la operacin Instance.

z Consecuencias:
{ Acceso controlado a la nica instancia. { Espacio de nombre reducido. Mejora sobre el uso de variables globales. { Permite el refinamiento de operaciones p y la representacin. p Se p puede subclasificar de la clase Singleton y configurar la aplicacin con una instancia de esta clase. { Fcil modificacin para permitir un nmero variable de instancias. { Ms flexible que las operaciones de clase.
17

Singleton
z Implementacin:
class Singleton { p private: static Singleton* _instance; void otherOperations(); protected: Singleton(); public: static Singleton* getInstance(); }; Singleton* Singleton::_instance = 0; Singleton* Singleton::getInstance() { if (_instance == 0 ) _instance instance = new Singleton; return _instance; }

18

#include "stdafx.h" #include <iostream> using namespace std; class Maze{ int x, y; public: M Maze(int (i x, i int y) ) : x(x), ( ) y(y) ( ) {} }; class MazeFactory { public: bli static MazeFactory* Instance(); // existing interface goes here Maze * createMaze(int x, int y) { return new Maze(x, y); }; protected: t t d MazeFactory() {}; private: static MazeFactory* _instance; }; MazeFactory* MazeFactory::_instance = 0; MazeFactory* M F t * MazeFactory::Instance M F t I t () { if (_instance == 0) _instance = new MazeFactory; return _instance; } void main(){ Maze * m = MazeFactory::Instance()->createMaze(10,10); }

Ejemplo

19

Singleton
z Implementacin:
{ Creacin de una subclase de singleton. { Determinar D t i qu singleton i l t queremos usar en l la operacin i I Instance. t { Registro de objetos singleton.
class Singleton { public: static void Register(const char* name, Singleton*); static Singleton* Singleton Instance(); protected: static Singleton* Lookup(const char* name); private: static Singleton* _instance; static List<NameSingletonPair>* _registry; }; Singleton* Si l t * Si Singleton::Instance l t I t () { if (_instance == 0) { const char* singletonName =getenv("SINGLETON"); // user use o or e environment o e supp supplies es this sa at s startup a up _instance = Lookup(singletonName); // Lookup returns 0 if there's no such singleton } return _instance; }

20

Singleton
z Dnde se registra la clase?
{ Una posibilidad es en el constructor.
MySingleton::MySingleton() { // ... Singleton::Register("MySingleton", g g ( y g this); ) }

{ Entonces hay que instanciar la clase! { Se puede crear una instancia global:
static MySingleton theSingleton;

21

Singleton g
Ejemplo
class MazeFactory { public: static MazeFactory* Instance(); // existing g interface g goes here protected: MazeFactory(); private: static MazeFactory MazeFactory* _instance; instance; }; MazeFactory* MazeFactory::_instance = 0; MazeFactory MazeFactory::Instance () { MazeFactory* if (_instance == 0) { const char* mazeStyle = getenv("MAZESTYLE"); if (strcmp(mazeStyle, "bombed") == 0) _instance i t = new B BombedMazeFactory; b dM F t } else if (strcmp(mazeStyle, "enchanted") == 0) _instance = new EnchantedMazeFactory; // ... other possible subclasses } else _instance = new MazeFactory;

return _instance; }

22

Abstract Factory
z Propsito. P it
{ Proporciona una interfaz para crear familias de objetos relacionados o que dependen entre s, sin especificar sus clases l concretas.

z Tambin Conocido Como.


{ Kit. Kit

z Motivacin.
{ Ej.: un framework para la construccin de interfaces de usuario que permita varios look and feel f (ej.: ( Motif f y Presentation Manager). z Una clase abstracta WidgetFactory con la interfaz para crear cada tipo de widget. widget z Una clase abstracta para cada tipo de widget. Subclases concretas que implementan cada widget concreto. z De esta manera, manera los clientes son independientes del look and feel concreto. 23

Abstract Factory
z Motivacin.
WidgetFactory CreateScrollBar() CreateWindow() Client

Productos
Window

Familias
PMWindow MotifWidgetFactory CreateScrollBar() CreateWindow() PMWindowFactory CreateScrollBar() CreateWindow() ScrollBar MotifWindow

PMScrollBar

MotifScrollBar

24

Abstract Factory
z Aplicabilidad. Usar este patrn cuando:
{ un sistema que deba ser independiente de cmo se crean, componen y representan sus productos. d { un sistema que deba ser configurado con una familia de productos entre varias. varias { una familia de objetos producto relacionados que est diseada para ser usada conjuntamente, conjuntamente y es necesario hacer cumplir esta restriccin. quiere p proporcionar p una biblioteca de clases { se q productos, y slo se quiere revelar sus interfaces, no su implementacin.
25

Abstract Factory
z Estructura:
AbstractFactory createProductA () createProductB () Client

Productos
AbstractProductA

Familias
ProductA2 ConcreteFactory1 createProductA () createProductB () ConcreteFactory2 createProductA () createProductB () AbstractProductB ProductA1

ProductB2

ProductB1

26

Abstract Factory
z Participantes: p
{ AbstractFactory. Declara una interfaz para operaciones que crean objetos producto abstractos. y Implementa p las operaciones p para crear objetos p j { ConcreteFactory. producto concretos. { AbstractProduct. Declara una interfaz para un tipo de objeto producto. { ConcreteProduct. Define un objeto producto para que sea creado por la fbrica correspondiente. { Client. Slo usa interfaces declaradas por las clases Ab t tF t AbstractFactory y AbstractProduct. Ab t tP d t

z Colaboraciones.
{ Normalmente slo se crea una nica instancia de una clase ConcreteFactory en tiempo de ejecucin. Esta fbrica concreta crea objetos producto que tienen una determinada implementacin. { AbstractFactory Ab t tF t d l delega l creacin la i de d objetos bj t producto d t en su subclase ConcreteFactory. 27

Abstract Factory
z Consecuencias. C i
{Asla las clases concretas. Ayuda a controlar las clases de objetos que crea una aplicacin. Asla a los clientes de las clases de implementacin. implementacin {Facilita el reemplazo de familias de productos. {Promueve P l consistencia la i t i entre t productos d t (que ( la aplicacin use objetos de una sola familia a la vez). vez) {Es difcil aadir un nuevo producto.
28

Abstract Factory
Ejemplo

Ejemplo: aplicacin para construir un coche a partir de unas partes (motor, chasis, ...)

todos t d los l componentes t de d la l misma i marca (familia) (f ili ) hay mltiples marcas (Ford, Toyota, Opel, ...) es responsabilidad p del cliente ensamblar las p piezas

Car

CarPart FordCar ToyotaCar PorscheCar

CarEngine

CarBody

FordEngine

ToyotaEngine

PorscheEngine

FordBody

ToyotaBody

PorscheBody

29

Abstract Factory
Ejemplo (ii)

Cmo lo haramos sin utilizar el patrn Abstract Factory? En un mtodo del cliente:
CrearCoche (string marca) { if (marca == ford) FordCar coche = new FordCar () else if (marca == toyota) ToyotaCar coche = new ToyotaCar () else ; if (marca == ford) FordEngine motor = new FordEngine () else if (marca == toyota) ToyotaEngine motor = new ToyotaEngine () else ; coche.add (motor); ... return coche; }
30

El cdigo del cliente decide qu clase de coche construir (bien) y qu subpartes instanciar (mal). Puede cometerse el error de ensamblar partes de distintas familias familias.

Abstract Factory
Ejemplo (iii)
CarPartFactory makeCar () makeBody y () makeEngine () Client

Productos
CarBody

Familias
ToyotaFactory makeCar () makeBody () makeEngine () FordFactory makeCar () makeBody () makeEngine ()

FordBody

ToyotaBody

CarEngine

FordEngine

ToyotaEngine

Car

FordCar

ToyotaCar
31

Abstract Factory
Ejemplo (iv)

Utilizando el patrn, ste fuerza a que todos los productos sean de la misma familia, una vez establecida sta por el cliente. El patrn permite separar la eleccin de la familia (la marca del coche) del proceso de instanciar las partes. En el cliente:
Car hacerCoche () { Car coche=familia.makeCar(); coche.addEngine (familia.makeEngine()); coche.addBody (familia.makeBody ()); ... return t coche; h }

32

Abstract Factory
Ejemplo (v)
familia contiene una instancia de una marca de coche. coche Cmo se instancia familia?

class CrearCoche { CarPartFactory y * familia; ; //presenta por pantalla la seleccin class CrearCocheGUI : public CFrameWnd { //. void id O OnButtonClicked B tt Cli k d () { string familiasel; CrearCoche assembler; Car coche; // // if (familiasel == ford) assembler=CrearCoche::using (new FordFactory()) else if (familiasel == toyota) assembler=CrearCoche::using bl C C h i ( (new T ToyotaFactory()) t F t ()) else ; coche = assembler.hacerCoche(); } } } Car hacerCoche () { Car coche=familia->makeCar(); coche.addEngine g ( (familia->makeEngine()); g ()); coche.addBody (familia->makeBody ()); ... return coche; } static CrearCoche using (CarPartFactory * f) { CrearCoche l; l.factory y (f); ( ); return l; } void factory y (CarPartFactory ( y * f) ){ familia=f; }

33

Abstract Factory
Otro Ejemplo: Laberinto
MazeFactory
+MakeMaze(): Maze +MakeWall(): Wall +MakeRoom(int n): Room +MakeDoor(Room r1, Room r2): Door

MazeGame
+CreateMaze(MazeFactory): Maze

Maze EnchantedMazeFactory
+MakeRoom(int n): EnchantedRoom +MakeDoor(Room r1, Room r2): DoorNeedingSpell

Wall

Room

Bombed Wall Door

Enchanted Room RoomWithA Bomb

BombedMazeFactory
+MakeRoom(int n): RoomWithABomb +MakeWall(): BombedWall

DoorNeeding Spell

34

Abstract Factory
Otro Ejemplo: Laberinto

class MazeFactory { public: MazeFactory(); virtual it lM Maze* *M MakeMaze() k M () const t { return new Maze; } virtual Wall* MakeWall() const { return new Wall; ;} virtual Room* MakeRoom(int n) const { return new Room(n); } virtual Door* MakeDoor(Room* r1, Room* r2) const { return t new Door(r1, D ( 1 r2); 2) } };

35

Abstract Factory
Otro Ejemplo
Maze* MazeGame::CreateMaze (MazeFactory& factory) { Maze* aMaze = factory.MakeMaze(); Room* r1 = factory.MakeRoom(1); Room Room* r2 = factory.MakeRoom(2); Door* aDoor = factory.MakeDoor(r1, r2); aMaze->AddRoom(r1); aMaze->AddRoom(r2); M AddR ( 2) r1->SetSide(North, factory.MakeWall()); r1->SetSide(East, aDoor); r1->SetSide(South, ( , factory.MakeWall()); y ()); r1->SetSide(West, factory.MakeWall()); r2->SetSide(North, factory.MakeWall()); r2->SetSide(East, factory.MakeWall()); r2->SetSide(South, 2 >S tSid (S th factory.MakeWall()); f t M k W ll()) r2->SetSide(West, aDoor); return aMaze; }
36

Abstract Factory
Otro Ejemplo
class EnchantedMazeFactory : public MazeFactory { public: EnchantedMazeFactory(); virtual Room* MakeRoom(int n) const { return new EnchantedRoom(n, CastSpell()); } virtual Door* MakeDoor(Room* r1, Room* r2) const { return new DoorNeedingSpell(r1, g p ( , r2); ); } protected: Spell* CastSpell() const; }; // Make it possible to have rooms with bombs MazeGame game; BombedMazeFactory y factory; y; Wall* BombedMazeFactory::MakeWall () const { Wall game.CreateMaze(factory); return new BombedWall; } Room* BombedMazeFactory::MakeRoom(int n) const { return t new RoomWithABomb(n); R WithAB b( ) } 37

Factory Method
z Propsito. P it
{ Define una interfaz para crear un objeto, pero deja que sean las subclases q quienes decidan q qu clase instanciar. Permite que una clase delegue en sus subclases la creacin de objetos.

z Tambin Conocido Como.


{ Virtual Constructor.

z Motivacin.
{ Ej.: un framework que pueda presentar distintos tipos de documentos (similar a MFCs). z Dos abstracciones clave: aplicacin p y documento ( (ambas clases abstractas). Hay que subclasificarlas. z La clase aplicacin no sabe qu subclase documento instanciar.
38

Factory Method
z Motivacin.
Documento +Abrir() b () +Cerrar() +Guardar() +Deshacer()
docs 1..* Se le llama factory method (mtodo de fabricacin)

Aplicacion +CrearDocumento() +NuevoDocumento() +AbrirDocumento()


Documento * doc = CrearDocumento() d docs.push_back(doc) h b k(d ) doc->Abrir()

MiAplicacion MiDocumento +CrearDocumento() C D t ()


return new MiDocumento

39

Factory Method
z A Aplicabilidad. li bilid d Usar U este patrn cuando: d { Una clase no puede prever la clase de los objetos que tiene que crear. { Una clase quiere que sean sus subclases las que decidan qu objetos crean. { Las clases delegan la responsabilidad en una de entre varias clases auxiliares y queremos localizar qu subclase concreta es en la que se auxiliares, delega. z Estructura.
Creator +FactoryMethod() +AnOperation()
// product = factoryMethod() //

P d t Product

C ConcreteProduct t P d t

C ConcreteCreator t C t +FactoryMethod()
return new ConcreteProduct
40

Factory Method
z Participantes. P ti i t
{ Product (Documento). Define la interfaz de los objetos que crea y method. el factory { ConcreteProduct (MiDocumento). Implementa la interfaz del producto. { Creator (Aplicacion). (Aplicacion) Declara el factory method. method Puede tambin dar una implementacin por defecto del factory method, que devuelve un objeto de una clase por defecto. { ConcreteCreator (MiAplicacion). (MiAplicacion) Sobreescribe el factory method para devolver una instancia de ConcreteProduct.

z Colaboraciones.
{ El creator se apoya en sus subclases para definir el mtodo de fabricacin de manera que ste devuelva una instancia del ConcreteProduct adecuado.
41

Factory Method
z Consecuencias Consecuencias. { Los mtodos de fabricacin eliminan la necesidad de ligar g clases especficas p de la aplicacin p a nuestro cdigo. { El cdigo slo trata con la interfaz Product, puede funcionar con cualquier clase ConcreteProduct definida por el usuario. { Proporciona enganches para las subclases. Crear objetos con un mtodo de fabricacin es ms flexible que hacerlos directamente. { El factory f t method th d es un hook h k method th d para que las l 42 subclases den una versin extendida del cdigo.

Factory Method
z Consecuencias.
Figure +CreateManipulator() p () Manipulator +DownClick() +Drag() g() +UpClick()

LineFigure +CreateManipulator()

TextFigure +CreateManipulator()

LineManipulator +DownClick() +Drag() +UpClick()

TextManipulator +DownClick() +Drag() +UpClick()

43

Factory Method
z Implementacin. I l t i
{Dos variantes principales:
z Cuando la clase Creator es abstracta y no proporciona implementacin para el mtodo de fabricacin que declara. declara z Cuando la clase Creator es concreta y proporciona una implementacin predeterminada para el mtodo de fabricacin.

{Mtodos de fabricacin parametrizados:


z Que Q l los f t factory methods th d creen varios i ti tipos d de producto. El mtodo recibe un parmetro que identifica el tipo p de objeto j a crear.
44

Factory Method
z Implementacin.
class Creator { public: Product* GetProduct(); protected: virtual Product* CreateProduct(); // factory method private: Product* _product; }; Product* Creator::GetProduct () { if (_product ( d t == 0) { _product = CreateProduct(); } ret rn _product; return prod ct }

45

Factory Method
z Implementacin. Se pueden usar plantillas para evitar la herencia (mltiples subclases de Creator).
class Creator { public: virtual Product* CreateProduct() = 0; // pure virtual factory method }; template <class TheProduct> class StandardCreator: public Creator { public: virtual TheProduct* CreateProduct(); }; template <class TheProduct> TheProduct* StandardCreator<TheProduct>::CreateProduct () { return new TheProduct; } // El cliente proporciona slo la clase del // producto, no necesita hacer una // nueva clase que herede de creator. class MyProduct : public Product { public: MyProduct(); // ... }; StandardCreator<MyProduct> myCreator;

46

Factory Method
Ejemplo
class MazeGame { public: Maze* CreateMaze(); (); // factory methods: virtual Maze* MakeMaze() const { return new Maze; } virtual Room* MakeRoom(int n) const { return new Room(n); } virtual Wall* MakeWall() const { return new Wall; } virtual Door* MakeDoor(Room* r1, Room* r2) const { return new Door(r1, r2); } }; Maze* MazeGame::CreateMaze () { Maze* aMaze = MakeMaze(); Room* r1 = MakeRoom(1); Room Room* r2 = MakeRoom(2); Door* theDoor = MakeDoor(r1, r2); aMaze->AddRoom(r1); aMaze->AddRoom(r2); M AddR ( 2) r1->SetSide(North, MakeWall()); r1->SetSide(East, theDoor); r1->SetSide(South, ( , MakeWall()); ()); r1->SetSide(West, MakeWall()); r2->SetSide(North, MakeWall()); r2->SetSide(East, MakeWall()); r2->SetSide(South, 2 >S tSid (S th MakeWall()); M k W ll()) r2->SetSide(West, theDoor); return aMaze; }
47

Factory Method
Ejemplo
class BombedMazeGame : public MazeGame { public: BombedMazeGame(); virtual Wall* Wall MakeWall() const { return new BombedWall; } virtual Room* MakeRoom(int n) const { return new RoomWithABomb(n); } }; class EnchantedMazeGame : public MazeGame { public: bli EnchantedMazeGame(); virtual Room* MakeRoom(int n) const { return new EnchantedRoom(n, ( , CastSpell()); p ()); } virtual Door* MakeDoor(Room* r1, Room* r2) const { return new DoorNeedingSpell(r1, r2); } protected: S ll* C Spell* CastSpell() tS ll() const; t };

48

Indice
z Introduccin. I t d i z Patrones de Creacin.

zPatrones P t E Estructurales. t t l
{Composite. Co pos te {Facade. {Proxy. Pro {Adapter.
z Patrones de Comportamiento. z Conclusiones. z Bibliografa.

49

Patrones Estructurales
z Establecen E t bl cmo se componen clases l y objetos bj t para formar estructuras mayores que implementan nueva funcionalidad. funcionalidad z Los patrones de clase usan la herencia para componer interfaces o implementaciones (ej.: (ej : Adapter). z Los patrones de objeto, objeto describen maneras de componer objetos para implementar nueva funcionalidad. funcionalidad
{ Flexibilidad, ya que se puede cambiar la configuracin en tiempo de ejecucin.
50

Composite
z Propsito.
{ componer objetos en estructuras representar jerarquas parte-conjunto. arborescentes para

z Motivacin. M ti i
{ Aplicaciones grficas. Manipulacin de grupos de figuras de manera uniforme. uniforme
Grafico dibuja ()

*
graficos

Linea dibuja ()

Rectangulo dibuja ()

Texto dibuja ()

Dibujo dibuja () aade (Grafico g) elimina (Grafico g) obtenHijo (int) para todo g en graficos g.dibuja () aadir g a la lista de 51 graficos: graficos.addElement (g)

Composite
z Una instancia en tiempo de ejecucin:
:Dibujo
graficos graficos graficos

:Dibujo
graficos graficos

:Linea

:Texto

:Rectangulo

:Texto

Composite
z Aplicabilidad. Usar el patrn cuando: { Se quieren representar jerarquas todo/parte de objetos. { Se quiere que los clientes ignoren la diferencia entre composiciones de objetos j y objetos j individuales. Los clientes tratarn todos los objetos j en la estructura compuesta de manera uniforme. z Estructura.
Client Component + Operation() + Add(Component) ( p ) + Remove(Component) + GetChild(int)

children

Leaf + Operation()

Composite + Operation() p () + Add(Component) + Remove(Component) + GetChild(int) forall g in children: g.Operation() O ti ()


53

Composite
z Participantes. p
{ Component (Grafico).
z Declara la interfaz de los objetos de la composicin. z Implementa p el comportamiento p por defecto de la interfaz comn a p todas las clases. z Declara las interfaces para acceder y gestionar los hijos. z (opcional) Define una interfaz para acceder al padre de un componente en la estructura recursiva y la implementa, implementa si es apropiado. apropiado

{ Leaf (Linea, Rectangulo, ).


z Representa objetos hoja en la composicin. Una hoja no tiene hijos. z Define el comportamiento de los objetos primitivos en la composicin. composicin

{ Composite (Dibujo)
z Define el comportamiento de los objetos con hijos en la composicin. z Almacena componentes hijo. hijo z Implementa operaciones relacionadas con los hijos de la interfaz de Component.

{ Client.
z Manipula objetos en la composicin a travs de la interfaz de 54 Component.

Composite
z Colaboraciones. Colaboraciones
{ Los clientes usan el interfaz de la clase Component para interaccionar con los objetos de la estructura compuesta. { Si el l objeto bj t es hoja, h j entonces t l peticin la ti i se cursa directamente. di t t { Si el objeto es un Composite, entonces normalmente redirige las peticiones a sus objetos hijo, quiz realizando operaciones adicionales antes y/o despus de la redireccin.

z Consecuencias. El patron composite:


{ Define jerarquas de objetos primitivos y compuestos. compuestos Cuando un cdigo cliente espera un objeto simple, se puede reemplazar por uno compuesto. { Simplifica el cliente. cliente Se pueden tratar objetos simples y compuestos de manera uniforme. { Facilita aadir nuevos tipos de componente. { Puede hacer el diseo demasiado general. Complicado restringir 55 los tipos de componente de un composite.

Composite
z Implementacin. I l t i Algunas Al d decisiones: i i
{ Referencias explcitas a los padres. En la clase component. { Compartir componentes. til para ahorrar memoria, pero la gestin de un componente que tiene ms de un padre es difcil. { Maximizar la interfaz del componente. { Declaracin de las operaciones de gestin de hijos hijos. Equilibrio entre seguridad y transparencia:
z Declararla en la raz da transparencia. Es menos seguro porque el cliente puede tratar de hacer cosas sin sentido sobre objetos hoja hoja. z Declararla en la clase compuesto da seguridad, pero perdemos transparencia: leafs y composites tienen interfaces distintas.

{ A veces es necesario tener en cuenta un orden para los hijos hijos. { Quin debe borrar los componentes? { Cul es la mejor estructura de datos para almacenar los componentes?. ?
56

Composite
Ejemplo
class Equipment { public: virtual ~Equipment(); const char* Name() { return _name; } virtual it lW Watt tt Power(); P () virtual Currency NetPrice(); virtual Currency DiscountPrice(); virtual void Add(Equipment*); Add(Equipment ); virtual void Remove(Equipment*); virtual Iterator* CreateIterator() {return 0;} protected: E i Equipment(const t( t char*); h *) private: const char* _name; };

57

Composite
Ejemplo
class FloppyDisk : public Equipment { public: p FloppyDisk(const char*); virtual ~FloppyDisk(); virtual Watt Power(); virtual Currency NetPrice(); virtual Currency DiscountPrice(); }; class CompositeEquipment : public Equipment { public: virtual ~CompositeEquipment(); virtual Watt Power(); (); virtual Currency NetPrice(); virtual Currency DiscountPrice(); virtual void Add(Equipment*); virtual void Remove(Equipment*); virtual Iterator* CreateIterator(); protected: CompositeEquipment(const p q p ( char*); ) private: List _equipment; };

58

Composite
Ejemplo
Currency CompositeEquipment::NetPrice () { Iterator* i = CreateIterator(); Currency total = 0; for (i->First(); (i >First(); !i->IsDone(); !i >IsDone(); i i->Next()) >Next()) { total += i->CurrentItem()->NetPrice(); } delete i; return total; } class Chassis : public CompositeEquipment { public: Chassis(const char*); virtual ~Chassis(); virtual it lW Watt tt Power(); P () virtual Currency NetPrice(); virtual Currency DiscountPrice(); };
59

Composite
Ejemplo
using namespace std; void main() { Cabinet* cabinet = new Cabinet("PC Cabinet"); Chassis* chassis = new Chassis( Chassis("PC PC Chassis Chassis"); ); cabinet->Add(chassis); Bus* bus = new Bus("MCA Bus"); bus->Add(new ( Card("16Mbs ( Token Ring")); g )) chassis->Add(bus); chassis->Add(new FloppyDisk("3.5in Floppy")); cout << "The net price is " << chassis->NetPrice() << endl; }

60

Facade
z Propsito.
{ Proporciona p una interfaz unificada p para un conjunto j de interfaces de un subsistema. { Define una interfaz de alto nivel que hace que el subsistema sea ms fcil de usar.

z Motivacin.
{ Estructurar un sistema en subsistemas ayuda a reducir su complejidad. { Un objetivo tpico de diseo es minimizar la comunicacin y dependencias entre subsistemas. { Un modo de conseguir esto es introducir un objeto fachada que proporcione una interfaz nica y simplificada a los servicios ms generales del subsistema.

61

Facade
z Motivacin.

62

Facade
z Aplicabilidad. Usar el patrn cuando: { Queramos proporcionar una interfaz simple a un subsistema complejo. Slo los clientes que necesitan ms personalizacin necesitarn ir ms all de la fachada. { Haya muchas dependencias entre los clientes y las clases que implementan una abstraccin. La fachada desacopla el subsistema de sus clientes y otros subsistemas (mejora acoplamiento y portabilidad). { Queramos dividir en capas nuestros subsistemas. La fachada es el punto de entrada a cada subsistema. z Estructura. E t t

63

Facade
z Participantes.
{ Facade (Compiler).
z Sabe qu clases del subsistema son las responsables ante una peticin. peticin z Delega las peticiones de los clientes en los objetos apropiados del subsistema.

{ Clases del Subsistema (Scanner, (Scanner Parser, Parser ProgramNodeBuilder, ProgramNodeBuilder CodeGenerator).
z Implementan la funcionalidad del subsistema. por el objeto j Facade. z Realizan las labores encomendadas p z No tienen referencias al objeto Facade.

z Observaciones.
{ Los clientes se comunican en el sistema enviando peticiones al objeto Facade, que las reenva a los objetos apropiados. { Los clientes que usan la fachada no tienen que acceder directamente a los objetos del subsistema.
64

Facade
z Consecuencias. C i
{ Oculta a los clientes los componentes del sistema, haciendo el sistema ms fcil de usar. { Promueve acoplamiento dbil entre el subsistema y sus clientes.
z Elimina dependencias compilacin. y puede reducir el tiempo de

{ No impide que las aplicaciones usen las clases del subsistema en caso necesario. necesario

z Implementacin. Factores a tener en cuenta:


{ Reduccin del acoplamiento cliente cliente-subsistema. subsistema. Clase facade abstracta, con clases concretas para las diferentes implementaciones de un subsistema. { Clases del subsistema pblicas o privadas. privadas Uso de espacios de nombres en C++. 65

Facade
Ejemplo: Una fachada para un sistema de compilacin
class Scanner { public: Scanner(istream&); virtual ~Scanner(); virtual it lT Token& k &S Scan(); () private: istream& _inputStream; }; class Parser { public: Parser(); virtual ~Parser(); virtual void Parse(Scanner&, ProgramNodeBuilder&); } };

66

Facade
Ejemplo: Una fachada para un sistema de compilacin
class ProgramNodeBuilder g { public: ProgramNodeBuilder(); virtual ProgramNode* NewVariable virtual ProgramNode* NewAssignment

( const char* variableName ) const; ( ProgramNode* variable variable, ProgramNode* expression) const; virtual ProgramNode* NewReturnStatement ( ProgramNode* value ) const; virtual ProgramNode* g NewCondition ( ProgramNode* g condition, ProgramNode* truePart, ProgramNode* falsePart ) const; // ... ProgramNode* GetRootNode(); ProgramNode private: ProgramNode* _node; };

67

Facade
Ej Ejemplo: l Una U f fachada h d para un sistema i t de d compilacin il i
class ProgramNode { public: // program node manipulation virtual void GetSourcePosition(int& line, int& index); // ... // child manipulation virtual void Add(ProgramNode*); virtual void Remove(ProgramNode*); // ... virtual void Traverse(CodeGenerator&); protected: ProgramNode(); }; class CodeGenerator { public: virtual void Visit(StatementNode*); virtual i t l void id Vi Visit(ExpressionNode*); it(E i N d *) // ... protected: CodeGenerator(BytecodeStream&); CodeGe e a o ( y ecodeS ea &); protected: BytecodeStream& _output; };

68

Facade
Ejemplo: Una fachada para un sistema de compilacin
void ExpressionNode::Traverse (CodeGenerator& cg) { cg.Visit(this); Vi it(thi ) ListIterator i(_children); for (i.First(); !i.IsDone(); i.Next()) { i.CurrentItem()->Traverse(cg); () ( g); } } class Compiler { // Clase Facade public: bli Compiler(); virtual void Compile(istream&, BytecodeStream&); }; void Compiler::Compile ( istream& input, BytecodeStream& output ) { Scanner scanner(input); P ProgramNodeBuilder N d B ild b builder; ild Parser parser; parser.Parse(scanner, builder); generator(output); ( p ); RISCCodeGenerator g ProgramNode* parseTree = builder.GetRootNode(); parseTree->Traverse(generator); }

69

Proxy
z Propsito. Propsito
{ Proporcionar un representante o substituto de otro objeto para controlar el acceso a este.

z Tambin conocido como.


{ Surrogate (substituto).

z Motivacin. M ti i
{ Retrasar el coste de creacin e inicializacin de un objeto que sea realmente necesario. hasta q { Ej.: al abrir un documento, no abrir las imgenes que no sean visibles.
aTextDocument: image anImageProxy: fileName data
70

anImage:

en memoria

en disco

Proxy
z Motivacin.

71

Proxy
z Aplicabilidad.
{ Cuando hay necesidad de una referencia a un objeto ms flexible o sofisticada que un puntero. { Proxy Remoto: un representante para un objeto que se encuentra en otro espacio de direcciones. { Proxy Virtual: Crea objetos costosos por encargo (ej.: I ImageProxy P ) ). { Proxy de Proteccin: Controla el acceso al objeto original (permisos de acceso). { Referencia inteligente: sustituto de un puntero, que lleva a cabo operaciones adicionales cuando se accede a un objeto (ver ejemplo operadores C++):
z Contar C t el l nmero d referencias. de f i z Cargar un objeto persistente en memoria. z Bloquear el objeto cuando se accede a l (no modificacin concurrente) concurrente). z 72

Proxy
z Estructura.

73

Proxy
z Participantes.
{ Proxy.
z Mantiene una referencia que permite al proxy acceder al objeto real. z Proporciona una interfaz igual que la del sujeto real. z Controla el acceso al sujeto real, y puede ser responsable de crearlo y borrarlo. z Otras responsabilidades, dependen del tipo de proxy:
Proxy Remoto: codifican las peticiones peticiones, y se las mandan al sujeto sujeto. Proxy virtual: Puede guardar informacin adicional sobre el sujeto, para retardar el acceso al mismo. Proxy de proteccin: comprueba que el llamador tiene permiso para realizar la peticin peticin.

{ Subject.
z Define una interfaz comn para el RealSubject y el Proxy, de tal manera que el Proxy se puede usan en vez del RealSubject RealSubject.

{ RealSubject.
z Define el objeto real que el proxy representa.

z Colaboraciones. Colaboraciones
{ El proxy redirige peticiones al sujeto real cuando sea necesario,74 dependiendo del tipo de proxy.

Proxy
z Consecuencias.
{ Introduce un nivel de indireccin adicional, que tiene muchos posibles usos:
z Un U proxy remoto t puede d ocultar lt el lh hecho h d de que un objeto bj t reside id en otro espacio de direcciones. z Un proxy virtual puede realizar optimizaciones, como crear objetos bajo demanda demanda. z Tanto los proxies de proteccin, como las referencias inteligentes permiten realizar tareas de mantenimiento adicionales cuando se accede a un objeto objeto.

{ Otra optimizacin: copy-on-write.


z Copiar un objeto grande puede ser costoso. z Si la copia no se modifica modifica, no hay necesidad de incurrir en dicho gasto. z El sujeto mantiene una cuenta de referencias, slo cuando se hace una operacin que modifica el objeto objeto, se copia realmente (ej (ej.: : clase String del ejemplo de operadores C++).

75

Proxy
z Implementacin. { Se pueden explotar las siguientes caractersticas de l lenguajes: los l j
z Sobrecargar el operador de acceso a miembros -> en C++ C++.

class Image; extern Image* LoadAnImageFile(const char*); // external function class ImagePtr { public: ImagePtr(const char* char imageFile); virtual ~ImagePtr(); virtual Image* operator->(); virtual Image& operator*(); private: Image* LoadImage(); private: Image* _image; Image image; const char* _imageFile; }; ImagePtr::ImagePtr (const char* theImageFile) { _imageFile = theImageFile; _image = 0; } Image* ImagePtr::LoadImage () { Image if (_image == 0) { _image = LoadAnImageFile(_imageFile); } return _image; 76 }

Proxy
Image ImagePtr::operator Image* ImagePtr::operator-> () { return LoadImage(); } Image& ImagePtr::operator* () { return t *LoadImage(); *L dI () } ImagePtr image = ImagePtr("anImageFileName"); image->Draw(Point(50, 100)); // (image.operator->())->Draw(Point(50, 100))

z Sobrecargar -> no funciona si necesitamos saber a qu operacin se llama: entonces hay que definir dichar operacin en el proxy y redirigir la llamada. llamada z A veces no hace falta que el proxy conozca el tipo concreto del sujeto real (si es suficiente con la interfaz de la clase abstracta Subject).
77

Proxy
Ejemplo: Un Proxy Virtual
class Graphic { public: virtual ~Graphic(); virtual void Draw(const Point& at) = 0; virtual void HandleMouse(Event& event) = 0; virtual const Point& GetExtent() = 0; virtual void Load(istream& from) = 0; virtual void Save(ostream& to) = 0; p protected: Graphic(); }; class Image : public Graphic { public: Image(const char* file); // loads image from a file virtual ~Image(); virtual void Draw(const Point& at); virtual void HandleMouse(Event& event); virtual const Point& GetExtent(); virtual void Load(istream& from); virtual void Save(ostream& to); private: // ... };

78

Proxy
Ejemplo: Un Proxy Virtual
class ImageProxy : public Graphic { // la clase proxy public: ImageProxy(const char* imageFile); virtual ~ImageProxy(); virtual i t l void id D Draw(const ( t Point& P i t& at); t) virtual void HandleMouse(Event& event); virtual const Point& GetExtent(); virtual void Load(istream& from); virtual void Save(ostream& to); protected: Image* GetImage(); private: i t Image* _image; Point _extent; char* c a _fileName; e a e; };

79

Proxy
Ejemplo: Un Proxy Virtual
ImageProxy::ImageProxy (const char char* fileName) { _fileName = strdup(fileName); _extent = Point::Zero; // don't know extent yet _image = 0; } Image* ImageProxy::GetImage() { if (_image == 0) { _image = new Image(_fileName); } return _image; } const Point& ImageProxy::GetExtent () { if (_extent ( t t == Point::Zero) P i t Z ){ _extent = GetImage()->GetExtent(); } return _extent; } void ImageProxy::Draw (const Point& at) { GetImage()->Draw(at); } void ImageProxy::HandleMouse (Event& event) { GetImage()->HandleMouse(event); }

void ImageProxy::Save (ostream& to) { to << _extent << _fileName; } void ImageProxy::Load (istream& from) { from >> _extent >> _fileName; }
80

Proxy
Ejemplo: Un Proxy Virtual
class TextDocument { public: TextDocument(); void Insert(Graphic*); // ... }; TextDocument* text = new TextDocument; // ... text->Insert(new ImageProxy("anImageFileName"));

81

Ejercicio (Junio de 208)


z Sea S l la aplicacin li i d de pedidos did vista i t en t temas anteriores: t i

Ejercicio
z En el contexto de la aplicacin anterior, supn que slo se puede acceder al disponible de una cuenta de pago si se ha introducido una clave. Utilizando patrones de diseo, implementa en C++ un Proxy de Proteccin que asegure que se accede al disponible de la cuenta slo si la clave es correcta (supn que la clave se pide por la consola). La clave se almacena en el proxy, y ste recuerda si ya se ha introducido correctamente o no.

#include "stdafx.h" #include <iostream> #include <string> using std::cout; using std::string; using std::cin; class Cuenta { public: virtual int obtenerDisponible () = 0; }; class CuentaReal : public Cuenta { private: int disponible; public: CuentaReal (int d ) : disponible (d) {} int obtenerDisponible() {return disponible; } }; class ProxyCuenta: public Cuenta { private: CuentaReal * cuenta; string clave; bool correcta; bool intro; public: ProxyCuenta ( string psswd, psswd CuentaReal & c ) : clave(psswd), cuenta(&c), intro(false), correcta(false) {} int obtenerDisponible(); };

Solucin (1)

int ProxyCuenta::obtenerDisponible() { if (correcta) return cuenta->obtenerDisponible(); else if (!intro) { intro = true; string cl; cout << "Introduce la clave:\n"; cin >> cl; if (cl == clave) { correcta = true; return cuenta->obtenerDisponible(); } else { correcta = false; cout << "clave incorrecta\n"; return -1; } } return -1; } void main() { CuentaReal c (100); ProxyCuenta pc ("clave1", c); int d = pc.obtenerDisponible(); cout << "Disponible = " << d << "\n"; cout << "Disponible = " << pc.obtenerDisponible(); }

Solucin (2)

Adapter
z Propsito.
{ Convierte el interfaz de una clase en otro q que espera p el cliente. { El adapter permite trabajar juntas a clases que de otra forma no podran por tener interfaces incompatibles.

z Tambin conocido como.


{ Wrapper (envoltorio).

z Motivacin.
{ A veces una clase de una biblioteca que ha sido diseada para reutilizarse reutilizarse, no puede hacerlo porque su interfaz no coincide con la interfaz especfica de dominio que requiere la aplicacin. { Ej.: Ej : un editor de dibujo dibujo. Objetos grficos grficos, con una clase base abstracta Shape.
z Queremos reutilizar una clase existente TextView para implementar TextShape (quiz no tengamos el cdigo fuente de TextView). z Solucin: Definir una clase TextShape que adapte el interfaz de TextView a Shape. z Se puede hacer de dos maneras:
Adaptador de clase: Heredando el interfaz de Shape y la implementacin de TextView. 86 Adaptador de objeto: Componiendo un objeto TextView dentro de un TextShape, e implementando TextShape en trminos de la interfaz de TextView.

Adapter
z Motivacin.
{ Adaptador p de objeto. j

87

Adapter
z Estructura.
{Adaptador p de clase.

88

Adapter
z Estructura.
{Adaptador p de objeto. j

89

Indice
z Introduccin. z Patrones de Creacin. z Patrones Estructurales.

z Patrones de Comportamiento Comportamiento.


{Iterator. {Observer. {Template Method. {State. gy {Strategy. {Command. {Chain of Responsibility. Responsibility
z Conclusiones. z Bibliografa.
90

Patrones de Comportamiento
z Tratan sobre algoritmos y la asignacin de p entre objetos. j responsabilidades z Describen no slo patrones de clases y objetos sino patrones de comunicacin objetos, entre ellos. z Caracterizan un flujo de control complejo, difcil de seguir en tiempo de ejecucin. z Permiten que el diseador se concentre slo l en cmo i interconectar t t objetos. bj t

Iterator
z Propsito.
{ Proporciona un medio de acceder a los elementos de un contenedor secuencialmente sin exponer su representacin interna. interna

z Tambin Conocido Como.


{ Cursor.

z Motivacin.
{ Un contenedor (p.ej.: una lista) debe proporcionar un medio de g sus datos secuencialmente sin exponer p su navegar representacin interna. { Se debe poder atravesar la lista de varias maneras, dependiendo de lo que se quiera hacer. { Probablemente no interesa aadir a la lista operaciones para realizar los diferentes recorridos. { Puede necesitarse hacer ms de un recorrido simultneamente. { Dar la responsabilidad de acceder y recorrer el objeto lista a un 92 objeto Iterator.

Iterator
z Motivacin.
List 1 + Count() + Append(Element) + Remove(Element)
list

ListIterator - index + First() + Next() + IsDone() + CurrentItem()

{ Antes de instanciar el ListIterator, se ha de proporcionar la lista. { Una vez que se tiene la instancia, se puede acceder a los elementos de la lista secuencialmente secuencialmente. { Separar el mecanismo de recorrido del objeto lista, nos permite definir iteradores que implementen distintas estrategias.
93

Iterator
z Motivacin.
{ El iterador y la lista estn acoplados: el cliente sabe que lo que se est recorriendo es una lista. { Es mejor poder cambiar el contenedor sin tener que cambiar el cdigo cliente: iteracin polimrfica. AbstractList +CreateIterator() + Count() + Append(Element) A d(El t) + Remove(Element) 1
skiplist

Cli t Client

Iterator + First() + Next() + IsDone() + CurrentItem()

SkipList

List 1 list

ListIterator *

SkipListIterator *

{ Podemos hacer responsables a las listas de crear sus propios iteradores, mediante un factory method (CreateIterator). 94 { Se puede definir algoritmos generales que usan un iterador genrico (en C++: for_each, find_if, count, etc)

Iterator
z Aplicabilidad. Usar el patrn : { para acceder al contenido de un contenedor sin exponer su representacin interna. { para permitir varios recorridos sobre contenedores. { para proporcionar una interfaz uniforme para recorres distintos tipos de contenedores (esto es, permitir la iteracin polimrfica).

z Estructura.
Aggregate +CreateIterator () Client

Iterator +First () +Next () +IsDone IsDone () +CurrentItem ()

ConcreteAggregate +CreateIterator () ConcreteIterator

return new ConcreteIterator (this)

95

Iterator
z Participantes. Participantes
{ Iterator.
z Define una interfaz para recorrer los elementos y acceder a ellos.

{ ConcreteIterator.
z Implementa la interfaz Iterator. z Mantiene la posicin actual en el recorrido del agregado.

{ Aggregate.
z Define una interfaz para crear un objeto Iterator.

{ ConcreteAggregate.
z Implementa una interfaz de creacin del Iterator para devolver una instancia del ConcreteIterator apropiado.

z Colaboraciones.
{ Un ConcreteIterator sabe cul es el objeto actual del agregado y puede calcular el objeto siguiente del recorrido.

96

Iterator
z Consecuencias.
{ Permite variaciones en el recorrido de un agregado. { Los iteradores simplifican la interfaz del contenedor. { Se puede hacer ms de un recorrido a la vez sobre un agregado.

z Implementacin.
{ Quin controla la iteracin?.
z El cliente controla la iteracin: iterador externo. z El iterador controla la iteracin: iterador interno.

{ Quin define el algoritmo de recorrido?


z El iterador. z El agregado, d y el l it iterador d slo l almacena l el l estado t d d de l la iteracin. A este tipo de iterador se le llama cursor.

{ Cmo de robusto es el iterador?


z Iterador robusto: Las inserciones y borrados no interfieren en el recorrido (y se hace sin copiar el agregado). 97

Iterator
z Implementacin. I l t i
{ Operaciones adicionales del iterador.
z Por ejemplo, iteradores ordenados podran tener una operacin Previous. Otras como SkipTo.

{ Usar iteradores polimrficos en C++.


z Los iteradores polimrficos han de crearse dinmicamente por un mtodo de fabricacin. z El cliente adems es responsable de borrarlos (propenso a errores). errores)

{ Iteradores para Composites.


z Los iteradores externos pueden ser complicados de implementar en estructuras t t recursivas. i

{ NullIterators.
z Es un iterador degenerado g q que ayuda y a manejar j condiciones lmite.
98

Iterator
Ejemplo
1 Interfaces de la lista y el iterador 1. iterador.
template <class Item> class List { public: List(long size = DEFAULT_LIST_CAPACITY); 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(); };

99

Iterator
Ejemplo
2 Implementaciones de las subclases del iterador 2. iterador.
template <class Item> class ListIterator : public Iterator<Item> { public: ListIterator(const List<Item>* aList) _list(aList), _current(0) {} virtual void First() {_current = 0;} virtual void Next() {_current++;} virtual bool IsDone() const {return _current >= _list->Count(); } virtual Item CurrentItem() const; private: const List<Item>* List<Item> _list; list; long _current; }; template <class Item> Item ListIterator<Item>::CurrentItem () const { if (IsDone()) throw IteratorOutOfBounds; return _list->Get(_current); } // Se puede implementar un ReverseListIterator, con First // posicionando el iterador al final de la lista, y Next decrementando

100

Iterator
Ejemplo
3 U 3. Uso d del li iterador. d
void PrintEmployees (Iterator<Employee*>& i) { for ( (i.First(); (); !i.IsDone(); (); i.Next()) ()) { i.CurrentItem()->Print(); } } List<Employee*>* employees; // ... ListIterator<Employee*> forward(employees); ReverseListIterator<Employee*> backward(employees); PrintEmployees(forward); PrintEmployees(backward);

101

Iterator
Ejemplo
4. Evitar ajustarse j a una implementacin p concreta de la lista.
{ Supongamos que tenemos SkipList y SkipListIterator. { Se puede introducir un AbstractList para estandarizar la interfaz de la lista (List y SkipList p son subclases de AbstractList). ) { Para permitir iteracin polimrfica, AbstractList define un factory method CreateIterator.
template <class Item> class AbstractList { public: virtual Iterator<Item>* CreateIterator() const = 0; // ... }; template <class Item> Iterator<Item>* List<Item>::CreateIterator () const { return new ListIterator<Item>(this); }

// we know only y that we have an AbstractList AbstractList<Employee*>* employees; // ... Iterator<Employee*>* iterator = employees->CreateIterator(); P i tE l PrintEmployees(*iterator); (*it t ) delete iterator;

102

Iterator
Ejemplo
5. Asegurarse g de que q los iteradores se borran.
{ Crear un IteratorPtr, que actua de Proxy para un Iterator. { Se ocupa de borrar el Iterator cuando se sale de mbito.
template <class Item> class IteratorPtr { public: IteratorPtr(Iterator<Item>* i): _i(i) i(i) { } ~IteratorPtr() { delete _i; } Iterator<Item>* operator->() { return _i; } Iterator<Item>& operator*() p () { return *_i; _ } private: // disallow copy and assignment to avoid // multiple deletions of _i: IteratorPtr(const IteratorPtr&); IteratorPtr& operator=(const IteratorPtr&); private: Iterator<Item>* _ _i; };

AbstractList<Employee*>* employees; // ... I IteratorPtr<Employee*> P E l * iterator(employees->CreateIterator()); PrintEmployees(*iterator);

103

Iterator
Ejemplo
6. Un iterador interno.
{ El iterador controla la iteracin, y aplica una operacin a cada elemento. { La operacin se puede configurar:
z Pasando un puntero a una funcin funcin, o a un objeto funcin funcin. z Mediante subclasificacin.
template <class Item> template <class Item> class ListTraverser { bool ListTraverser<Item>::Traverse () { public: bool result = false; ListTraverser(List<Item>* aList):_iterator(aList) { }; for ( _iterator.First(); iterator First(); ! !_iterator.IsDone();_iterator.Next()) iterator IsDone(); iterator Next()) { bool Traverse(); result = ProcessItem(_iterator.CurrentItem()); protected: if (result == false) break; virtual bool ProcessItem(const Item&) = 0; } private: return result; ListIterator<Item> _iterator; } };

104

Iterator
Ejemplo
6 U 6. Un i iterador d i interno
{ Imprimir los n primeros empleados de una lista.
class PrintNEmployees : public ListTraverser<Employee*> { public: PrintNEmployees(List<Employee*>* aList, int n) : ListTraverser<Employee*>(aList), p y ( ) _total(n), _count(0) { } protected: bool ProcessItem(Employee* const&); private: int _total; int _count; } }; bool PrintNEmployees::ProcessItem (Employee* const& e) { _count++; e >Print(); e->Print(); return _count < _total; }

105

Iterator
Ejemplo
6 U 6. Un it iterador d i interno t
{ Imprimir los n primeros empleados de una lista.
List Employee List<Employee*>* employees; // ... PrintNEmployees pa(employees, 10); pa.Traverse();

{ Comparacin con un iterador externo:


ListIterator<Employee*> i(employees); int count = 0; for (i.First(); !i.IsDone(); i.Next()) { count++; i.CurrentItem()->Print(); if (count >= 10) break; }

106

Iterator
Ejemplo
6 U 6. Un i iterador d i interno
{ Pueden encapsular distintos tipos de operaciones.
template <class Item> template <class Item> class FilteringListTraverser { void FilteringListTraverser<Item>::Traverse () { public: bool result = false; FilteringListTraverser(List<Item>* aList); for (_ (_iterator.First();!_iterator.IsDone();_iterator.Next()) () _ () _ ()) { bool Traverse(); () if (TestItem(_iterator.CurrentItem())) { protected: result = ProcessItem(_iterator.CurrentItem()); virtual bool ProcessItem(const Item&) = 0; if (result == false) break; virtual bool TestItem(const ( Item&) ) = 0; } private: } ListIterator<Item> _iterator; return result; }; }

107

Observer
z Propsito P it .
{ Define una dependencia de uno-a-muchos entre objetos, de que cuando un objeto j cambie de estado se notifique q y forma q actualicen automticamente todos los objetos que dependen de l.

z Tambin conocido como.


{ Dependents, Publish-Subscribe

z Motivacin.
{ Mantener consistencia entre objetos relacionados. { No queremos obtener dicha consistencia aumentando el acoplamiento entre clases. clases { Ej.: separacin de la presentacin en GUI de los datos de aplicacin subyacente.
108

Observer
z Motivacin.
40
D A

A X Y
B

B 20 25 10

C 15 15 20

D 5 20 60

30 20 10 0 A B C D

60 40 10

Modelo
A: B: C C: D: 40% 25% 15% 20%

109

Observer
z Aplicabilidad. { Cuando una abstraccin tiene dos aspectos y uno depende del otro. { Cuando un cambio en un objeto requiere cambiar otros, y no sabemos cuntos hay yq que cambiar. { Cuando un objeto debera ser capaz de notificar a otros sin hacer suposiciones sobre quines son dichos objetos (esto es, no queremos que los objetos estn fuertemente acoplados). acoplados) z Estructura.
Subject +Attach (Observer) +Detach (Observer) +Notify ()
observers

0 1 0..1 forall o in observers o.Update()

1 * 1..*

Observer +Update()

ConcreteObserver ConcreteSubject - subjectState +GetState () +SetState () return subjectState 0..1


subject

- observerState +Update () observerState= subject->GetState()


110

Observer
z Participantes.
{ Subject. S bj t
z Conoce a sus observadores, que pueden ser un nmero arbitrario. z Proporciona un interfaz para aadir y quitar objetos Observer.

{ Observer. Ob
z Define un interfaz de actualizacin para los objetos que deben ser notificados sobre cambios en un sujeto.

{ ConcreteSubject. ConcreteSubject
z Almacena estado de inters para ConcreteObservers. z Manda notificaciones a sus observadores cuando su estado cambia.

{ ConcreteObserver. ConcreteObserver
z Mantiene una referencia a objetos ConcreteSubject. z Almacena el estado que debe ser consistente con el del sujeto. z Implementa el interfaz de actualizacin del Observer para mantener su estado consistente con el del sujeto.

111

Observer
z Colaboraciones. { El ConcreteSubject notifica a sus observadores cada vez que se produce un cambio que pudiera hacer que el estado de estos fuese inconsistente con el suyo. y { Despus de ser notificado del cambio, un ConcreteObserver puede pedir al subject ms informacin.
:ConcreteSubject
SetState() Notify() Update() GetState() Update() GetState()

barDiagram :ConcreteObserver

sectorDiagram :ConcreteObserver

112

Observer
z Consecuencias. Consecuencias
{ Permite modificar los sujetos y observadores de manera independiente. { Se S pueden d reutilizar tili l los sujetos j t sin i sus observadores b d y viceversa. { Se pueden aadir observadores sin modificar el sujeto u otros observadores. observadores { Acoplamiento abstracto entre sujeto y observador. El sujeto no conoce la clase concreta de ningn observador (el acoplamiento es mnimo). mnimo) { Capacidad de comunicacin mediante difusin. La notificacin del sujeto se enva automticamente a todos los observadores pueden aadir y q quitar observadores en cualquier q suscritos. Se p momento. { Actualizaciones inesperadas. Una operacin aparentemente inofensiva sobre el sujeto puede desencadenar una cascada de cambios bi en los l observadores. b d
113

Observer
z Implementacin.
{ Correspondencia entre sujetos y observadores.
z Que el sujeto guarde referencias a los observadores a los que debe notificar. notificar

{ Observar ms de un sujeto.
z Ej.: una hoja de clculo puede observar ms de un origen de datos. z Extender la interfaz de actualizacin para que el observador sepa qu sujeto se ha actualizado (quiz simplemente el sujeto se pase a s mismo como parmetro del update()).

{ Q Quin dispara p la actualizacin?


z Las operaciones que cambien el estado del sujeto llaman a Notify().
Ventaja: los clientes no tienen que hacer nada. Inconveniente: no es ptimo si hay varios cambios de estado seguidos.

z Los clientes llaman a Notify():


Ventaja: se puede optimizar llamando a notify slo despus de varios cambios. Inconveniente: los clientes tienen la responsabilidad aadida de llamar a Notify().
114

Observer
z Implementacin.
{ Referencias perdidas a sujetos borrados.
z Una manera de evitarlo es notificar a los observadores cuando se borra un sujeto.

{ Asegurarse de que el estado del Sujeto sea consistente consigo mismo antes de la notificacin:
z Hay que tener cuidado con las operaciones heredadas.
void MySubject::Operation (int newValue) { BaseClassSubject::Operation(newValue); // trigger notification _myInstVar += newValue; // update subclass state (too late!) }
115

Observer
z Implementacin. Implementacin
{ Evitar protocolos especficos del obervador: los modelos push y pull.
z Las implementaciones de observer suelen hacer que el sujeto envie informacin adicional como parmetro de Update(). z Dos extremos:
Modelo Push: el sujeto enva informacin detalla del cambio cambio, quieran los observadores o no. Inconveniente: observadores menos reutilizables. Modelo Pull: el sujeto no enva nada, y los observadores piden d despus l los d detalles t ll explcitamente. l it t Inconveniente: puede ser poco eficiente.

{ Especificar las modificaciones de inters explcitamente:


z Mejorar la eficiencia haciendo que los observadores registren solo aquellos eventos que les interesen. z Los observadores se subscriben a aspectos del sujeto.
116

Observer
z Implementacin.
{ Encapsular la semntica de las operaciones complejas complejas.
z Si la relacin de dependencia entre sujetos y observadores es compleja, puede ser necesario un objeto intermedio para la gestin de cambios (ChangeManager). z Minimizar el trabajo j necesario p para q que los observadores reflejen j los cambios en el sujeto. z Ej.: si varios sujetos han de cambiarse, asegurarse de que se notifique a los observadores slo despus del cambio en el ltimo sujeto.
Subject +Attach (Observer o) +Detach (Observer) +Notify () chman->Notify() chman >Notify() chman->Registar(this,o) SimpleChangeManager forall s in subjects: forall o in observers: o->Update(s) +Register (Subject,Observer) +Unregister (Subject,Observer) +Notify () DAGChangeManager +Register (Subject,Observer) +Unregister (Subject,Observer) +Notify ()
subjects chman

0..*

ChangeManager Subject-Observer mapping +Register (Subject,Observer) +Unregister (Subject,Observer) +Notify ()

observers

Observer +Update(Subject)

1..*

Marcar todos los observers a actualizar. Actualizar los observers marcados.

117

Observer
Ejemplo
class Subject; class Observer { public: virtual ~ Observer(); () virtual void Update (Subject* theChangedSubject) = 0; // soporte de mltiples subjects protected: Observer(); }; class Subject { public: virtual ~Subject(); j () virtual void Attach(Observer*); virtual void Detach(Observer*); virtual void Notify(); protected: Subject(); private: List<Observer*> *_observers; _ }; void Subject::Attach (Observer* o) { _observers->Append(o); } void Subject::Detach (Observer* o) { _observers->Remove(o); } void Subject::Notify () { ListIterator<Observer*> i(_observers); for (i.First(); !i.IsDone(); i.Next()) { i CurrentItem() >Update(this); i.CurrentItem()->Update(this); } 118 }

Observer
Ejemplo
class ClockTimer : public Subject { // Concrete subject public: ClockTimer(); () virtual int GetHour(); virtual int GetMinute(); virtual int GetSecond(); void Tick(); }; void ClockTimer::Tick () { // update internal time-keeping state // ... Notify(); } class DigitalClock: public Widget, public Observer { public: DigitalClock(ClockTimer*); virtual i t l ~DigitalClock(); Di it lCl k() virtual void Update(Subject*); // overrides Observer operation virtual void Draw(); // overrides Widget operation; // defines how to draw the digital clock private: Cl kTi ClockTimer* * _subject; bj t }; DigitalClock::DigitalClock (ClockTimer* s) { _subject bj t = s; _subject->Attach(this); } DigitalClock::~DigitalClock DigitalClock:: DigitalClock () { _subject->Detach(this); }

119

Observer
Ejemplo
void DigitalClock::Update (Subject* theChangedSubject) { if (theChangedSubject == _subject) Draw(); } void DigitalClock::Draw () { int hour = _subject->GetHour(); // get the new values from the subject int minute = _subject->GetMinute(); // etc. // draw the digital clock } class AnalogClock : public Widget Widget, public Observer { public: AnalogClock(ClockTimer*); virtual void Update(Subject*); virtual void Draw(); // ... }; ClockTimer* timer = new ClockTimer; AnalogClock* analogClock = new AnalogClock(timer); DigitalClock* digitalClock = new DigitalClock(timer);
120

Observer
Usos Conocidos

z Sistemas de eventos en Java (observer=listener) (observer listener)


{ AWT/Swing { Javabeans

z MVC en el sistema de ventanas de Smalltalk


{ Model=Subject { View=Observer { Controller=Cualquier objeto que cambie el estado de Subject

z MVC en entornos web (J2EE)


{ Model=EJB { View=JSP { Controller Controller=servlet servlet

121

Template Method
z Propsito p . { Definir el esqueleto de un algoritmo, delegando en las subclases alguno de sus pasos. { Permite que las subclases cambien pasos de un algoritmo sin cambiar su estructura. z Motivacin. { Ej.: MFCs, abrir un fichero.
Document +Abrir() +Cerrar() +Guardar() +DoRead() D R d() docs 1 * 1..* Application pp +AddDocument() +OpenDocument() +DoCreateDocument() +CanOpenDocument() +AboutToOpenDocument()

MyDocument y +DoRead()
return MyDocument

MyApplication +DoCreateDocument() +CanOpenDocument() +AboutToOpenDocument()

void Application::OpenDocument (const char* name) { if (!CanOpenDocument(name)) { // cannot handle this document return; } Document* doc = DoCreateDocument(); if (doc) { _docs->AddDocument(doc); AboutToOpenDocument(doc); doc->Open(); doc >DoRead(); doc->DoRead(); } 122 }

Template Method
z Aplicabilidad.
{ Para implementar las partes de un algoritmo que no cambian, y dejar que las subclases implementen el comportamiento que puede variar variar. { Cuando el comportamiento repetido de varias subclases debera factorizarse y localizarse en una clase comn, para evitar cdigo duplicado. { Para controlar las extensiones de las subclases.

z Estructura. E t t

ClaseAbstracta +TemplateMethod() +PrimitiveOperation1() +PrimitiveOperation2() +

PrimitiveOperation1() PrimitiveOperation2()

ConcreteClass +PrimitiveOperation1() +PrimitiveOperation2()


123

State
z Propsito.
{ Permitir que un objeto modifique su comportamiento cada vez que cambie su estado interno. { Parecer que cambia la clase del objeto.

z Tambin conocido como.


{ Objets for state (estados como objetos).

z Motivacin.
{ TCPConnection p para representar p una conexin de red. { Puede estar en distintos estados: establecida, escuchando y cerrada. { El efecto de cada peticin sobre cada objeto depende del estado en el que est.

124

State
z Estructura.

125

Strategy
z Propsito.
{ Define una familia de algoritmos, encapsula cada uno de ellos, y los hace intercambiables. { Permite que un algoritmo vare independientemente de los clientes que los usan.

z Tambin conocido como.


{ Policy (poltica).

z Motivacin. Motivacin
{ Ej.: Algoritmos para dividir en lneas un flujo de texto. { Clases que encapsulen los distintos algoritmos de divisin. Un algoritmo as encapsulado se denomina estrategia.

126

Strategy
z Estructura.

127

Command
z Propsito. { Encapsula peticiones a objetos objetos. { Permite parametrizar a los clientes con diferentes peticiones, hacer cola o llevar un registro de peticiones, as como deshacer las peticiones. peticiones z Tambin conocido como. { Action, Transaction. z Motivacin. M ti i
{ Framework grfico tipo MFC. Peticiones de los distintos widgets encapsuladas como objetos.

128

Command
z Motivacin. M ti i

129

Command
z Estructura. E t t

130

Chain of Resposibility
z Propsito. { Evita acoplar el emisor de una peticin a su receptor, dando a ms de un objeto la posibilidad de responder a la peticin. { Encadena los objetos receptores y pasa la peticin a travs de la cadena hasta que es procesada por algn objeto. z Motivacin. { Ej.: ayuda sensible al contexto en una GUI. { Si no existe ayuda para una parte de la interfaz, se muestra ayuda para una p p parte ms g general.

131

Chain of Resposibility
z Motivacin.

132

Chain of Resposibility
z Estructura.

133

Indice
z z z z Introduccin. I t d i Patrones de Creacin. Patrones Estructurales. Estructurales Patrones de Comportamiento.

z Conclusiones. Conclusiones
z Bibliografa.

134

Conclusiones
z Los patrones de diseo capturan el conocimiento que tienen los expertos a la hora de disear. z Los patrones ayudan a generar software maleable (software que soporta y facilita el cambio, la reutilizacin y la mejora). mejora) z Los patrones de diseo son guas, no reglas rigurosas. z Cada patrn describe la solucin a problemas que se repiten una y orta vez en nuestro entorno, entorno de forma que se puede usar esa solucin todas las veces que haga falta.
135

Indice
z z z z z Introduccin. I t d i Patrones de Creacin. Patrones Estructurales. Estructurales Patrones de Comportamiento. Conclusiones Conclusiones.

z Bibliografa.

136

Bibliografa
z Design D i patterns, tt elements l t of f reusable bl objectbj t oriented software. Gamma, Helm, Jonhnson, Vlissides Addison Wesley, Vlissides. Wesley 1995 (traducido al espaol en 2003). z Applying UML and Patterns. An introduction to Object Oriented Analysis and Design and Object-Oriented Iterative Development. 3rd Edition. Craig Larman Prentice Hall Larman. Hall.2005. 2005 z http://hillside.net/ http://hillside net/
137

También podría gustarte