Está en la página 1de 137

Patrones de Diseo

Tema 7
TACC II
Grupo 46
111
TACC II
Curso 2008/09
Indice Indice
I t d i Introduccin.
Patrones.
Descripcin de los Patrones.
Ejemplo: Patrones en el MVC de Smalltalk.
El catlogo de patrones.
Patrones de Creacin.
Patrones Estructurales.
Patrones de Comportamiento.
C l i Conclusiones.
Bibliografa.
222
Introduccin Introduccin
Di fi l bl l Diseo especfico para el problema, pero general como
para poder adecuarse a futuros requisitos y problemas.
Evitar el rediseo en la medida de lo posible.
Evitar resolver cada problema partiendo de cero.
Reutilizar soluciones que han sido tiles en el pasado.
Patrones recurrentes de clases y comunicacin entre
objetos en muchas soluciones de diseo.
3
Patrn Patrn
Un esquema que se usa para solucionar un problema Un esquema que se usa para solucionar un problema.
El esquema ha sido probado extensivamente, y ha El esquema ha sido probado extensivamente, y ha
funcionado. Se tiene experiencia sobre su uso.
E i t h d i i Existen en muchos dominios:
Novelas y el cine: hroe trgico, comedia romntica, etc.
Arte.
Ingenieras.
Arquitectura.
Christopher Alexander. A Pattern Language: Towns, Buildings, p g g , g ,
Construction. 1977.
http://www.patternlanguage.com
4
Patrones de Diseo Patrones de Diseo
R tili di b t t i l d t ll Reutilizar diseos abstractos que no incluyan detalles
de la implementacin.
Un patrn es una descripcin del problema y la esencia
de su solucin, que se puede reutilizar en casos q p
distintos.
E l i d d bl Es una solucin adecuada a un problema comn.
A i d i t i bj t l i i i Asociado a orientacin a objetos, pero el principio
general es aplicable a todos los enfoques de diseo
software.
5
Patrones de Diseo
D t l i i l di
Patrones de Diseo
Documentar la experiencia en el diseo, en
forma de un catlogo de patrones.
Categoras de patrones:
De creacin: implica el proceso de instanciar objetos.
Estructurales: composicin de objetos.
De comportamiento cmo se com nican los objetos De comportamiento: cmo se comunican los objetos,
cooperan y distribuyen las responsabilidades para
lograr sus objetivos.
6
Patrones de Diseo
Estructura de un patrn
N b d l t Nombre del patrn.
Describe el problema de diseo, junto con sus soluciones y
consecuencias.
V b l i d di Vocabulario de diseo.
Problema.
Describe cundo aplicar el patrn.
Explica el problema y su contexto.
Solucin.
Elementos que forman el diseo, relaciones, responsabilidades. Elementos que forman el diseo, relaciones, responsabilidades.
No un diseo concreto, sino una plantilla que puede aplicarse en
muchas situaciones distintas.
Consecuencias Consecuencias.
Resultados, ventajas e inconvenientes de aplicar el patrn.
P.ej.: relacin entre eficiencia en espacio y tiempo; cuestiones de
implementacin etc
7
implementacin, etc.
Patrones de Diseo
Ejemplo: MVC de Smalltalk
Modelo/Vista/Controlador.
40
A
C
D
10
20
30
40
A B C D
X 60 20 15 5
Y 40 25 15 20
B
0
A B C D
Y 40 25 15 20
Z 10 10 20 60
Modelo
A: 40%
B: 25%
C 15%
8
C: 15%
D: 20%
Patrones de Diseo
S l bj t l d t ( d l )
Ejemplo: MVC de Smalltalk
Separar los objetos con los datos (modelo), sus
visualizaciones (vistas) y el modo en que la interfaz
reacciona ante la entrada al usuario (controlador). ( )
Separar estos componentes, para aumentar la p p p
flexibilidad y reutilizacin.
D l i d d l di l d Desacoplar vistas de modelos, mediante un protocolo de
subscripcin/notificacin.
Cada vez que cambian los datos del modelo, avisar a
las vistas que dependen de l. Estas se actualizan.
9
q p
Patrones de Diseo
Patrn Observer ms general (dependencias entre
Ejemplo: MVC de Smalltalk
Patrn Observer, ms general (dependencias entre
objetos).
Las vistas se pueden anidar: Vistas compuestas y
simples.
Generalizacin: Patrn Composite Generalizacin: Patrn Composite.
La relacin entre la vista y el controlador: patrn
St t ( bj t t l it ) Strategy (un objeto que representa un algoritmo).
Otros patrones: Otros patrones:
Factory Method: especifica la clase controlador predeterminada
para una vista.
Decorator: Aade capacidad de desplazamiento a una vista
10
Decorator: Aade capacidad de desplazamiento a una vista.
El catlogo de patrones El catlogo de patrones
Propsito
Creacin Estructurales De Comportamiento
Clase
Factory Method Adapter (de clases) Interpreter.
Template Method Template Method.

m
Objeto
Abstract Factory Adapter (de objetos). Chain of Responsibility.
m
b
i
t
o
j
Builder
Prototype
Singleton
Bridge.
Composite.
Decorator.
Command.
Iterator.
Mediator.
Facade.
Flyweight.
Proxy.
Memento.
Observer.
State.
11
Proxy. State.
Strategy.
Visitor.
El catlogo
de patrones
Relaciones entre
los patrones.
12
Indice Indice
Introduccin Introduccin.
Patrones de Creacin.
Singleton Singleton.
Abstract Factory.
Factory Method.
Patrones Estructurales.
Patrones de Comportamiento.
Concl siones Conclusiones.
Bibliografa.
13 13 13
Patrones de Creacin Patrones de Creacin
Ab t l d i t i i Abstraen el proceso de instanciacin
Ayudan a que el sistema sea independiente de
cmo se crean componen y representan los cmo se crean, componen y representan los
objetos.
Flexibilizan: Flexibilizan:
qu se crea
quin lo crea
cmo se crea
cundo se crea
Permiten configurar un sistema: Permiten configurar un sistema:
estticamente (compile-time)
dinmicamente (run-time)
14
( )
Singleton Singleton
I t i Intencin.
Asegurar que una clase tiene una nica instancia y proporciona un
punto de acceso global a dicha instancia.
Motivacin.
Hay veces que es importante asegurar que una clase tenga una
sola instancia por ejemplo: sola instancia, por ejemplo:
Un gestor de ventanas
Una nica cola de impresin
Un nico sistema de ficheros 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, pero se puede instanciar varias veces.
Responsabilidad de la clase misma: actuar sobre el
mensaje de creacin de instancias
15
Singleton Singleton
Aplicabilidad.
Cuando debe haber una sola instancia, y debe ser accesible a los
clientes desde un punto de acceso conocido. 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 instancia extendida sin modificar su cdigo.
Estructura.
Singleton
static Singleton uniqueInstance
singletonData
static Singleton Instance ()
SingletonOperation ()
GetSingletonData ()
return uniqueInstance
16
Singleton Singleton
Participantes: p
Singleton:
Define una operacin de clase, llamada Instance que deja a los clientes
acceder a la nica instancia.
Puede ser responsable de crear su nica instancia.
Colaboraciones:
Los clientes acceden a la instancia de un Singleton a travs de la
operacinInstance.
Consecuencias:
Acceso controlado a la nica instancia.
Espacio de nombre reducido. Mejora sobre el uso de variables
globales.
Permite el refinamiento de operaciones y la representacin. Se puede p y p p
subclasificar de la clase Singleton y configurar la aplicacin con una
instancia de esta clase.
Fcil modificacin para permitir un nmero variable de instancias.
17
Ms flexible que las operaciones de clase.
Singleton Singleton
Implementacin: Implementacin:
class Singleton {
private: p
static Singleton* _instance;
void otherOperations();
protected:
Singleton();
public:
static Singleton* getInstance();
}};
Singleton* Singleton::_instance = 0;
Singleton* Singleton::getInstance() {
if (_instance == 0 )
instance =newSingleton;
18
_instance = new Singleton;
return _instance;
}
Ejemplo
#include "stdafx.h"
#include <iostream>
using namespace std;
Ejemplo
class Maze{
int x, y;
public:
M (i i ) ( ) ( ) {} Maze(int x, int y) : x(x), y(y) {}
};
class MazeFactory {
bli public:
static MazeFactory* Instance();
// existing interface goes here
Maze * createMaze(int x, int y) {return new Maze(x, y); };
t t d protected:
MazeFactory() {};
private:
static MazeFactory* _instance;
}};
MazeFactory* MazeFactory::_instance =0;
M F t * M F t I t () { MazeFactory* MazeFactory::Instance () {
if (_instance ==0) _instance =new MazeFactory;
return _instance;
}
19
void main(){
Maze * m =MazeFactory::Instance()->createMaze(10,10);
}
Singleton
Implementacin:
Creacin de una subclase de singleton.
D t i i l t l i I t Determinar qu singleton queremos usar en la operacin Instance.
Registro de objetos singleton.
class Singleton {
public:
static void Register(const char* name, Singleton*);
static Singleton* Instance(); static Singleton Instance();
protected:
static Singleton* Lookup(const char* name);
private:
static Singleton* _instance;
static List<NameSingletonPair>* _registry;
};
Si l t * Si l t I t () { Singleton* Singleton::Instance () {
if (_instance == 0) {
const char* singletonName =getenv("SINGLETON");
// user or environment supplies this at startup
20
// use o e o e supp es s a s a up
_instance = Lookup(singletonName); // Lookup returns 0 if there's no such singleton
}
return _instance; }
Singleton Singleton
Dnde se registra la clase?
Una posibilidad es en el constructor.
MySingleton::MySingleton() {
// ...
Singleton::Register("MySingleton", this);
Entonces hay que instanciar la clase!
g g ( y g )
}
Se puede crear una instancia global:
static MySingleton theSingleton;
21
Singleton g
Ejemplo
MazeFactory* MazeFactory::Instance () {
class MazeFactory {
public:
static MazeFactory* Instance();
// existing interface goes here
MazeFactory MazeFactory::Instance () {
if (_instance ==0) {
const char* mazeStyle =getenv("MAZESTYLE");
if (strcmp(mazeStyle, "bombed") ==0)
i t B b dM F t
g g
protected:
MazeFactory();
private:
static MazeFactory* instance;
_instance =new BombedMazeFactory;
}else if (strcmp(mazeStyle, "enchanted") ==0)
_instance =new EnchantedMazeFactory;
// ... other possible subclasses
static MazeFactory _instance;
};
MazeFactory* MazeFactory::_instance =0;
}else
_instance =new MazeFactory;
return _instance;
}}
22
Abstract Factory Abstract Factory
P it Propsito.
Proporciona una interfaz para crear familias de objetos
relacionados o que dependen entre s, sin especificar sus
l clases concretas.
Tambin Conocido Como.
Kit Kit.
Motivacin.
Ej.: un framework para la construccin de interfaces de usuario
f ( f que permita varios look and feel (ej.: Motif y Presentation
Manager).
Una clase abstracta WidgetFactory con la interfaz para crear
cada tipo de widget cada tipo de widget.
Una clase abstracta para cada tipo de widget. Subclases
concretas que implementan cada widget concreto.
De esta manera los clientes son independientes del look
23
De esta manera, los clientes son independientes del look
and feel concreto.
Abstract Factory Abstract Factory
Motivacin.
WidgetFactory
CreateScrollBar()
CreateWindow()
Client
Window
Productos
MotifWidgetFactory PMWindowFactory
MotifWindow PMWindow
Familias
MotifWidgetFactory
CreateScrollBar()
CreateWindow()
PMWindowFactory
CreateScrollBar()
CreateWindow()
ScrollBar
MotifScrollBar PMScrollBar
24
Abstract Factory Abstract Factory
Aplicabilidad. Usar este patrn cuando:
un sistema que deba ser independiente de cmo se
d crean, componeny representansus productos.
un sistema que deba ser configurado con una familia de
productos entre varias productos entre varias.
una familia de objetos producto relacionados que est
diseada para ser usada conjuntamente y es necesario diseada para ser usada conjuntamente, y es necesario
hacer cumplir esta restriccin.
se quiere proporcionar una biblioteca de clases q p p
productos, y slo se quiere revelar sus interfaces, no su
implementacin.
25
Abstract Factory Abstract Factory
Estructura:
AbstractFactory
createProductA ()
Client
Productos
()
createProductB () AbstractProductA
Familias
ConcreteFactory1
createProductA ()
createProductB ()
ConcreteFactory2
createProductA ()
createProductB ()
AbstractProductB
ProductA1
ProductA2
createProductB () createProductB ()
ProductB1 ProductB2
26
Abstract Factory Abstract Factory
Participantes: p
AbstractFactory. Declara una interfaz para operaciones que
crean objetos producto abstractos.
ConcreteFactory. Implementa las operaciones para crear objetos y p p p j
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 Ab t tP d t AbstractFactoryy AbstractProduct.
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.
Ab t tF t d l l i d bj t d t
27
AbstractFactory delega la creacin de objetos producto en su
subclase ConcreteFactory.
Abstract Factory
C i
Abstract Factory
Consecuencias.
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.
P l i t i t d t ( Promueve la consistencia entre productos (que
la aplicacin use objetos de una sola familia a
la vez) la vez).
Es difcil aadir un nuevo producto.
28
Abstract Factory Abstract Factory
Ejemplo
Ejemplo: aplicacin para construir un coche a partir
de unas partes (motor, chasis, ...)
t d l t d l i (f ili ) todos los componentes de la misma marca (familia)
hay mltiples marcas (Ford, Toyota, Opel, ...)
es responsabilidad del cliente ensamblar las piezas p p
Car
ToyotaCar FordCar PorscheCar
CarPart
CarBody
CarEngine
29
ToyotaBody FordBody PorscheBody
ToyotaEngine FordEngine PorscheEngine
Abstract Factory Abstract Factory
Ejemplo (ii)
Cmo lo haramos sin utilizar el patrnAbstract Factory? Cmo lo haramos sin utilizar el patrnAbstract Factory?
En un mtodo del cliente:
CrearCoche (string marca) {
if (marca ==ford)
FordCar coche =new FordCar ()
El cdigo del cliente
decide qu clase de
coche construir (bien)
else if (marca ==toyota)
ToyotaCar coche =new ToyotaCar ()
else ;
coche construir (bien)
y qu subpartes
instanciar (mal). Puede
if (marca ==ford)
FordEngine motor =new FordEngine ()
else if (marca ==toyota)
ToyotaEngine motor =new ToyotaEngine ()
cometerse el error de
ensamblar partes de
distintas familias
else ;
coche.add (motor);
...
distintas familias.
30
return coche;
}
Abstract Factory Abstract Factory
Ejemplo (iii)
CarPartFactory
makeCar ()
makeBody ()
Client
CarBody
Productos
y ()
makeEngine ()
CarBody
ToyotaBody
FordBody
Familias
ToyotaFactory
makeCar ()
FordFactory
makeCar ()
CarEngine
makeCar ()
makeBody()
makeEngine ()
makeCar ()
makeBody()
makeEngine ()
ToyotaEngine FordEngine
Car
31
ToyotaCar FordCar
Abstract Factory 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 ());
...
t h
32
return coche;
}
Abstract Factory
f ami l i a contiene una instancia de una marca de coche
Abstract Factory
Ejemplo (v)
f ami l i a contiene una instancia de una marca de coche.
Cmo se instancia f ami l i a?
class CrearCoche {
CarPartFactory * familia; y ;
Car hacerCoche () {
Car coche=familia->makeCar();
coche.addEngine (familia->makeEngine());
//presenta por pantalla la seleccin
class CrearCocheGUI : public CFrameWnd {
//.
idO B tt Cli k d() {
g ( g ());
coche.addBody (familia->makeBody ());
...
return coche;
}
void OnButtonClicked () {
string familiasel;
CrearCoche assembler;
Car coche;
//
}
static CrearCoche using (CarPartFactory * f) {
CrearCoche l;
l.factory (f);
//
if (familiasel ==ford)
assembler=CrearCoche::using (new FordFactory())
else if (familiasel ==toyota)
bl C C h i ( T t F t ())
y( );
return l;
}
void factory (CarPartFactory * f) {
assembler=CrearCoche::using (new ToyotaFactory())
else ;
coche =assembler.hacerCoche();
}
33
y( y ) {
familia=f;
}
}
}
}
Abstract Factory Abstract Factory
Otro Ejemplo: Laberinto
MazeFactory
+MakeMaze(): Maze
MazeGame
+CreateMaze(MazeFactory): Maze
+MakeWall(): Wall
+MakeRoom(int n): Room
+MakeDoor(Room r1, Room r2): Door
Maze Wall Room
EnchantedMazeFactory
+MakeRoom(int n): EnchantedRoom
+MakeDoor(Roomr1, Roomr2):
DoorNeedingSpell
Enchanted
Room
Bombed
Wall
Door
BombedMazeFactory
RoomWithA
Bomb
34 DoorNeeding
Spell
+MakeRoom(int n): RoomWithABomb
+MakeWall(): BombedWall
Abstract Factory Abstract Factory
Otro Ejemplo: Laberinto
class MazeFactory {
public:
MazeFactory();
i t l M * M k M () t virtual Maze* MakeMaze() const
{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
{ t D ( 1 2) } {return new Door(r1, r2); }
};
35
Abstract Factory Abstract Factory
Otro Ejemplo
Maze* MazeGame::CreateMaze (MazeFactory& factory) {
Maze* aMaze = factory.MakeMaze();
Room* r1 =factory.MakeRoom(1); Room r1 factory.MakeRoom(1);
Room* r2 = factory.MakeRoom(2);
Door* aDoor = factory.MakeDoor(r1, r2);
aMaze->AddRoom(r1);
M AddR ( 2) aMaze->AddRoom(r2);
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());
2 >S tSid (S th f t M k W ll()) r2->SetSide(South, factory.MakeWall());
r2->SetSide(West, aDoor);
return aMaze;
}
36
}
Abstract Factory Abstract Factory
Otro Ejemplo
class EnchantedMazeFactory : public MazeFactory {
public:
EnchantedMazeFactory();
virtual Room* MakeRoom(int n) const virtual Room* MakeRoom(int n) const
{return new EnchantedRoom(n, CastSpell()); }
virtual Door* MakeDoor(Room* r1, Room* r2) const
{return new DoorNeedingSpell(r1, r2); { g p ( , );
}
protected:
Spell* CastSpell() const;
}; };
// Make it possible to have rooms with bombs
Wall* BombedMazeFactory::MakeWall () const {
MazeGame game;
BombedMazeFactory factory;
Wall BombedMazeFactory::MakeWall () const {
return new BombedWall;
}
Room* BombedMazeFactory::MakeRoom(int n) const {
t R WithAB b( )
y y;
game.CreateMaze(factory);
37
return new RoomWithABomb(n);
}
Factory Method Factory Method
P it Propsito.
Define una interfaz para crear un objeto, pero deja que
sean las subclases quienes decidan qu clase instanciar. q q
Permite que una clase delegue en sus subclases la
creacin de objetos.
Tambin Conocido Como. Tambin Conocido Como.
Virtual Constructor.
Motivacin.
Ej.: un framework que pueda presentar distintos tipos de
documentos (similar a MFCs).
Dos abstracciones clave: aplicacin y documento (ambas p y (
clases abstractas). Hay que subclasificarlas.
La clase aplicacin no sabe qu subclase documento
instanciar.
38
Factory Method Factory Method
Motivacin.
Se le llama factory method (mtodo
de fabricacin)
Documento
+Abrir()
Aplicacion
+CrearDocumento()
docs
1..*
Documento * doc =CrearDocumento()
d h b k(d )
b ()
+Cerrar()
+Guardar()
+Deshacer()
CrearDocumento()
+NuevoDocumento()
+AbrirDocumento()
docs.push_back(doc)
doc->Abrir()
MiDocumento
MiAplicacion
C D t ()
return new MiDocumento
+CrearDocumento()
39
Factory Method Factory Method
A li bilid d U d Aplicabilidad. Usar este patrn cuando:
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 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, y queremos localizar qu subclase concreta es en la que se
delega.
Estructura.
Creator
P d t
Creator
+FactoryMethod()
+AnOperation()
//
product =factoryMethod()
//
Product
+AnOperation()
C t P d t C t C t
//
40
ConcreteProduct ConcreteCreator
+FactoryMethod()
return new ConcreteProduct
Factory Method
P ti i t
Factory Method
Participantes.
Product (Documento). Define la interfaz de los objetos que crea
el factorymethod. y
ConcreteProduct (MiDocumento). Implementa la interfaz del
producto.
Creator (Aplicacion) Declara el factory method Puede tambin Creator (Aplicacion). Declara el factory method. Puede tambin
dar una implementacin por defecto del factory method, que
devuelve un objeto de una clase por defecto.
ConcreteCreator (MiAplicacion) Sobreescribe el factory ConcreteCreator (MiAplicacion). Sobreescribe el factory
method para devolver una instancia de ConcreteProduct.
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
Consecuencias
Factory Method
Consecuencias.
Los mtodos de fabricacin eliminan la necesidad de
ligar clases especficas de la aplicacin a nuestro g p p
cdigo.
El cdigo slo trata con la interfaz Product puede 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 objetos con un mtodo de fabricacin es ms flexible
que hacerlos directamente.
El f t th d h k th d l
42
El factory method es un hook method para que las
subclases den una versin extendida del cdigo.
Factory Method Factory Method
Consecuencias.
Figure Manipulator Figure Manipulator
+DownClick()
+Drag()

+CreateManipulator() g()
+UpClick()
p ()

LineManipulator
+DownClick()
+Drag()
TextManipulator
+DownClick()
+Drag()
LineFigure

+CreateManipulator()
TextFigure

+CreateManipulator()
+Drag()
+UpClick()
+Drag()
+UpClick()
+CreateManipulator() +CreateManipulator()
43
Factory Method
I l t i
Factory Method
Implementacin.
Dos variantes principales:
Cuando la clase Creator es abstracta y no
proporciona implementacin para el mtodo de
fabricacinque declara fabricacinque declara.
Cuando la clase Creator es concreta y proporciona
una implementacin predeterminada para el mtodo
de fabricacin.
Mtodos de fabricacin parametrizados:
Q l f t th d i ti d Que los factory methods creen varios tipos de
producto. El mtodo recibe un parmetro que
identifica el tipo de objeto a crear.
44
p j
Factory Method Factory Method
Implementacin.
class Creator {{
public:
Product* GetProduct();
protected:
virtual Product* CreateProduct(); // factory method
private:
Product* _product;
};
Product* Creator::GetProduct () {
if ( d t 0) { if (_product == 0) {
_product = CreateProduct();
}
ret rn prod ct
45
return _product;
}
Factory Method Factory Method
Implementacin. Se pueden usar plantillas para evitar
la herencia (mltiples subclases de Creator).
class Creator {
public:
virtual Product* CreateProduct() = 0;
// El cliente proporciona slo la clase del
// producto, no necesita hacer una
// pure virtual factory method
};
template <class TheProduct>
class StandardCreator: public Creator {
// nueva clase que herede de creator.
class MyProduct : public Product {
public:
MyProduct();
class StandardCreator: public Creator {
public:
virtual TheProduct* CreateProduct();
};
MyProduct();
// ...
};
StandardCreator<MyProduct> myCreator;
template <class TheProduct>
TheProduct*
StandardCreator<TheProduct>::CreateProduct () {
46
StandardCreator<TheProduct>::CreateProduct () {
return new TheProduct;
}
Factory Method Factory Method
Ejemplo
class MazeGame {
public:
Maze* CreateMaze();
Maze* MazeGame::CreateMaze () {
Maze* aMaze = MakeMaze();
Room* r1 =MakeRoom(1);
();
// factory methods:
virtual Maze* MakeMaze() const
{return new Maze; }
virtual Room* MakeRoom(int n) const
Room r1 MakeRoom(1);
Room* r2 = MakeRoom(2);
Door* theDoor = MakeDoor(r1, r2);
aMaze->AddRoom(r1);
M AddR ( 2)
virtual Room* MakeRoom(int n) const
{return new Room(n); }
virtual Wall* MakeWall() const
{return new Wall; }
aMaze->AddRoom(r2);
r1->SetSide(North, MakeWall());
r1->SetSide(East, theDoor);
r1->SetSide(South, MakeWall());
{ }
virtual Door* MakeDoor(Room* r1, Room* r2) const
{return new Door(r1, r2); }
};
( , ());
r1->SetSide(West, MakeWall());
r2->SetSide(North, MakeWall());
r2->SetSide(East, MakeWall());
2 >S tSid (S th M k W ll()) r2->SetSide(South, MakeWall());
r2->SetSide(West, theDoor);
return aMaze;
}
47
}
Factory Method Factory Method
Ejemplo
class BombedMazeGame : public MazeGame {
public:
BombedMazeGame();
virtual Wall* MakeWall() const virtual Wall MakeWall() const
{return new BombedWall; }
virtual Room* MakeRoom(int n) const
{return new RoomWithABomb(n); }
};
class EnchantedMazeGame : public MazeGame {
bli public:
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 tS ll() t
48
Spell* CastSpell() const;
};
Indice Indice
I t d i Introduccin.
Patrones de Creacin.
P t E t t l Patrones Estructurales.
Composite. Co pos te
Facade.
Pro Proxy.
Adapter.
Patrones de Comportamiento.
Conclusiones.
49 49 49
Bibliografa.
Patrones Estructurales Patrones Estructurales
E t bl l bj t Establecen cmo se componen clases y objetos
para formar estructuras mayores que
implementan nueva funcionalidad implementan nueva funcionalidad.
Los patrones de clase usan la herencia para
componer interfaces o implementaciones (ej : componer interfaces o implementaciones (ej.:
Adapter).
Los patrones de objeto describen maneras de Los patrones de 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 Composite
Propsito.
componer objetos en estructuras arborescentes para
representar jerarquas parte-conjunto.
M ti i Motivacin.
Aplicaciones grficas. Manipulacin de grupos de figuras de
manera uniforme manera uniforme.
Grafico
dibuja ()
graficos
*
dibuja ()
Dibujo
dibuja ()
aade (Grafico g)
Linea
dibuja ()
Rectangulo
dibuja ()
Texto
dibuja ()
para todo g en graficos
g.dibuja ()
51
elimina (Grafico g)
obtenHijo (int)
aadir g a la lista de
graficos:
graficos.addElement (g)
Composite Composite
Una instancia en tiempo de ejecucin:
:Dibujo
Una instancia en tiempo de ejecucin:
:Linea :Texto :Dibujo
graficos graficos graficos
:Linea :Texto :Dibujo
graficos
graficos
:Rectangulo :Texto
Composite
Aplicabilidad. Usar el patrn cuando:
Composite
Se quieren representar jerarquas todo/parte de objetos.
Se quiere que los clientes ignoren la diferencia entre composiciones de
objetos y objetos individuales. Los clientes tratarn todos los objetos en j y j j
la estructura compuesta de manera uniforme.
Estructura.
Client Component
+ Operation()
+ Add(Component)
children
*
( p )
+ Remove(Component)
+ GetChild(int)
Composite
+ Operation()
forall g in children:
O ti ()
Leaf
+Operation()
53
p ()
+ Add(Component)
+ Remove(Component)
+ GetChild(int)
g.Operation()
+ Operation()
Composite Composite
Participantes. p
Component (Grafico).
Declara la interfaz de los objetos de la composicin.
Implementa el comportamiento por defecto de la interfaz comn a p p p
todas las clases.
Declara las interfaces para acceder y gestionar los hijos.
(opcional) Define una interfaz para acceder al padre de un componente
en la estructura recursiva y la implementa si es apropiado en la estructura recursiva y la implementa, si es apropiado.
Leaf (Linea, Rectangulo, ).
Representa objetos hoja en la composicin. Una hoja no tiene hijos.
Define el comportamiento de los objetos primitivos en la composicin Define el comportamiento de los objetos primitivos en la composicin.
Composite (Dibujo)
Define el comportamiento de los objetos con hijos en la composicin.
Almacena componentes hijo Almacena componentes hijo.
Implementa operaciones relacionadas con los hijos de la interfaz de
Component.
Client
54
Client.
Manipula objetos en la composicin a travs de la interfaz de
Component.
Composite Composite
Colaboraciones Colaboraciones.
Los clientes usan el interfaz de la clase Component para
interaccionar con los objetos de la estructura compuesta.
Si l bj t h j t l ti i di t t Si el objeto es hoja, entonces la peticin se cursa directamente.
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.
Consecuencias. El patron composite:
Define jerarquas de objetos primitivos y compuestos Cuando Define jerarquas de objetos primitivos y compuestos. Cuando
un cdigo cliente espera un objeto simple, se puede reemplazar
por uno compuesto.
Simplifica el cliente Se pueden tratar objetos simples y Simplifica el cliente. Se pueden tratar objetos simples y
compuestos de manera uniforme.
Facilita aadir nuevos tipos de componente.
55
Puede hacer el diseo demasiado general. Complicado restringir
los tipos de componente de un composite.
Composite Composite
I l t i Al d i i Implementacin. Algunas decisiones:
Referencias explcitas a los padres. En la clase component.
Compartir componentes. til para ahorrar memoria, pero la 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 Equilibrio Declaracin de las operaciones de gestin de hijos. Equilibrio
entre seguridad y transparencia:
Declararla en la raz da transparencia. Es menos seguro porque el
cliente puede tratar de hacer cosas sin sentido sobre objetos hoja cliente puede tratar de hacer cosas sin sentido sobre objetos hoja.
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 A veces es necesario tener en cuenta un orden para los hijos.
Quin debe borrar los componentes?
Cul es la mejor estructura de datos para almacenar los
?
56
componentes?.
Composite Composite
Ejemplo
class Equipment { class Equipment {
public:
virtual ~Equipment();
const char* Name() {return _name; }
i t l W tt P () virtual Watt Power();
virtual Currency NetPrice();
virtual Currency DiscountPrice();
virtual voidAdd(Equipment*); virtual void Add(Equipment );
virtual void Remove(Equipment*);
virtual Iterator* CreateIterator() {return 0;}
protected:
E i t( t h *) Equipment(const char*);
private:
const char* _name;
}; };
57
Composite
class FloppyDisk : public Equipment {
public:
Ejemplo
p
FloppyDisk(const char*);
virtual ~FloppyDisk();
virtual Watt Power();
virtual Currency NetPrice(); virtual Currency NetPrice();
virtual Currency DiscountPrice();
};
class CompositeEquipment : public Equipment { 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 void Remove(Equipment*);
virtual Iterator* CreateIterator();
protected:
CompositeEquipment(const char*);
58
p q p ( )
private:
List _equipment;
};
Composite Composite
Ejemplo
Currency CompositeEquipment::NetPrice () {
Iterator* i = CreateIterator();
Currency total = 0;
for (i->First(); !i->IsDone(); i->Next()) { for (i >First(); !i >IsDone(); i >Next()) {
total += i->CurrentItem()->NetPrice();
}
delete i;
return total;
}
class Chassis : public CompositeEquipment { class Chassis : public CompositeEquipment {
public:
Chassis(const char*);
virtual ~Chassis();
i t l W tt P () virtual Watt Power();
virtual Currency NetPrice();
virtual Currency DiscountPrice();
};
59
};
Composite Composite
Ejemplo
using namespace std;
void main()
{
Cabinet* cabinet = new Cabinet("PC Cabinet");
Chassis* chassis =newChassis("PC Chassis"); Chassis* chassis = new Chassis( PC 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 Facade
Propsito.
Proporciona una interfaz unificada para un conjunto de interfaces de un p p j
subsistema.
Define una interfaz de alto nivel que hace que el subsistema sea ms fcil
de usar.
Motivacin.
Estructurar un sistema en subsistemas ayuda a reducir su complejidad.
Un objetivo tpico de diseo es minimizar la comunicacin y dependencias 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 Facade
Motivacin.
62
Facade Facade
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). 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.
E t t Estructura.
63
Facade Facade
Participantes Participantes.
Facade (Compiler).
Sabe qu clases del subsistema son las responsables ante una
peticin peticin.
Delega las peticiones de los clientes en los objetos apropiados del
subsistema.
Clases del Subsistema (Scanner Parser ProgramNodeBuilder Clases del Subsistema (Scanner, Parser, ProgramNodeBuilder,
CodeGenerator).
Implementan la funcionalidaddel subsistema.
Realizanlas labores encomendadas por el objeto Facade. p j
No tienen referencias al objeto Facade.
Observaciones.
Los clientes se comunican en el sistema enviando peticiones al 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
directamente a los objetos del subsistema.
Facade Facade
C i Consecuencias.
Oculta a los clientes los componentes del sistema, haciendo
el sistema ms fcil de usar.
Promueve acoplamiento dbil entre el subsistema y sus
clientes.
Elimina dependencias y puede reducir el tiempo de Elimina dependencias y puede reducir el tiempo de
compilacin.
No impide que las aplicaciones usen las clases del
subsistema en caso necesario subsistema en caso necesario.
Implementacin. Factores a tener en cuenta:
Reduccin del acoplamiento cliente-subsistema. Clase Reduccin del acoplamiento cliente subsistema. Clase
facade abstracta, con clases concretas para las diferentes
implementaciones de un subsistema.
Clases del subsistema pblicas o privadas Uso de espacios
65
Clases del subsistema pblicas o privadas. Uso de espacios
de nombres en C++.
Facade Facade
Ejemplo: Una fachada para un sistema de compilacin
class Scanner { class Scanner {
public:
Scanner(istream&);
virtual ~Scanner();
i t l T k &S () virtual Token& Scan();
private:
istream& _inputStream;
}; };
class Parser {
public:
Parser(); Parser();
virtual ~Parser();
virtual void Parse(Scanner&, ProgramNodeBuilder&);
}; }
66
Facade
class ProgramNodeBuilder {
Facade
Ejemplo: Una fachada para un sistema de compilacin
g {
public:
ProgramNodeBuilder();
virtual ProgramNode* NewVariable ( const char* variableName ) const;
virtual ProgramNode* NewAssignment ( ProgramNode* variable virtual ProgramNode* NewAssignment ( ProgramNode* variable,
ProgramNode* expression) const;
virtual ProgramNode* NewReturnStatement ( ProgramNode* value ) const;
virtual ProgramNode* NewCondition ( ProgramNode* condition, g ( g
ProgramNode* truePart,
ProgramNode* falsePart ) const;
// ...
ProgramNode* GetRootNode(); ProgramNode GetRootNode();
private:
ProgramNode* _node;
};
67
Facade
Ej l U f h d i t d il i
class ProgramNode {
public:
// programnode manipulation
Ejemplo: Una fachada para un sistema de compilacin
// program node manipulation
virtual void GetSourcePosition(int& line, int& index);
// ...
// child manipulation
virtual void Add(ProgramNode*);
virtual void Remove(ProgramNode*);
// ...
virtual voidTraverse(CodeGenerator&); virtual void Traverse(CodeGenerator&);
protected:
ProgramNode();
};
class CodeGenerator {
public:
virtual void Visit(StatementNode*);
i t l id Vi it(E i N d *) virtual void Visit(ExpressionNode*);
// ...
protected:
CodeGenerator(BytecodeStream&);
68
CodeGe e a o ( y ecodeS ea &);
protected:
BytecodeStream& _output;
};
Facade
void ExpressionNode::Traverse (CodeGenerator& cg) {
Vi it(thi )
Facade
Ejemplo: Una fachada para un sistema de compilacin
cg.Visit(this);
ListIterator i(_children);
for (i.First(); !i.IsDone(); i.Next()) {
i.CurrentItem()->Traverse(cg); () ( g);
}
}
class Compiler { // Clase Facade
bli public:
Compiler();
virtual void Compile(istream&, BytecodeStream&);
}; };
void Compiler::Compile ( istream& input, BytecodeStream& output ) {
Scanner scanner(input);
P N d B ild b ild ProgramNodeBuilder builder;
Parser parser;
parser.Parse(scanner, builder);
RISCCodeGenerator generator(output);
69
g ( p );
ProgramNode* parseTree = builder.GetRootNode();
parseTree->Traverse(generator);
}
Proxy Proxy
Propsito Propsito.
Proporcionar un representante o substituto de otro objeto
para controlar el acceso a este.
Tambin conocido como.
Surrogate (substituto).
M ti i Motivacin.
Retrasar el coste de creacin e inicializacin de un objeto
hasta que sea realmente necesario. q
Ej.: al abrir un documento, no abrir las imgenes que no sean
visibles.
aTextDocument:
image
anImageProxy:
fileName
anImage:
data
70
en memoria
en disco
Proxy Proxy
Motivacin.
71
Proxy Proxy
Aplicabilidad 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 enotro espacio de direcciones.
Proxy Virtual: Crea objetos costosos por encargo (ej.:
I P ) ImageProxy).
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++):
C t l d f i Contar el nmero de referencias.
Cargar un objeto persistente en memoria.
Bloquear el objeto cuando se accede a l (no modificacin
concurrente)
72
concurrente).

Proxy Proxy
Estructura. Estructura.
73
Proxy Proxy
Participantes.
Proxy.
Mantiene una referencia que permite al proxy acceder al objeto real.
Proporciona una interfaz igual que la del sujeto real.
Controla el acceso al sujeto real, y puede ser responsable de crearlo y
borrarlo.
Otras responsabilidades, dependen del tipo de proxy:
Proxy Remoto: codifican las peticiones y se las mandan al sujeto Proxy Remoto: codifican las peticiones, y se las mandan al 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 realizar la peticin.
Subject.
Define una interfaz comn para el RealSubject y el Proxy, de tal
manera que el Proxy se puede usan en vez del RealSubject manera que el Proxy se puede usan en vez del RealSubject.
RealSubject.
Define el objeto real que el proxy representa.
Colaboraciones
74
Colaboraciones.
El proxy redirige peticiones al sujeto real cuando sea necesario,
dependiendo del tipo de proxy.
Proxy Proxy
Consecuencias Consecuencias.
Introduce un nivel de indireccin adicional, que tiene muchos
posibles usos:
U t d lt l h h d bj t id Un proxy remoto puede ocultar el hecho de que un objeto reside en
otro espacio de direcciones.
Un proxy virtual puede realizar optimizaciones, como crear objetos
bajo demanda bajo demanda.
Tanto los proxies de proteccin, como las referencias inteligentes
permiten realizar tareas de mantenimiento adicionales cuando se
accede a un objeto accede a un objeto.
Otra optimizacin: copy-on-write.
Copiar un objeto grande puede ser costoso.
Si la copia no se modifica no hay necesidad de incurrir en dicho Si la copia no se modifica, no hay necesidad de incurrir en dicho
gasto.
El sujeto mantiene una cuenta de referencias, slo cuando se hace
una operacin que modifica el objeto se copia realmente (ej : clase
75
una operacin que modifica el objeto, se copia realmente (ej.: clase
String del ejemplo de operadores C++).
Proxy
class Image;
extern Image* LoadAnImageFile(const char*);
Proxy
Implementacin
// external function
class ImagePtr {
public:
ImagePtr(const char* imageFile); Implementacin.
Se pueden explotar las
siguientes caractersticas de
l l j
ImagePtr(const char imageFile);
virtual ~ImagePtr();
virtual Image* operator->();
virtual Image& operator*();
los lenguajes:
Sobrecargar el operador de
acceso a miembros -> en
C++
private:
Image* LoadImage();
private:
Image* image;
C++.
Image _image;
const char* _imageFile;
};
ImagePtr::ImagePtr (const char* theImageFile) {
_imageFile = theImageFile;
_image = 0;
}
Image* ImagePtr::LoadImage () { Image ImagePtr::LoadImage () {
if (_image == 0) {
_image = LoadAnImageFile(_imageFile);
}
76
return _image;
}
Proxy Proxy
Image* ImagePtr::operator->() { Image ImagePtr::operator () {
return LoadImage();
}
Image& ImagePtr::operator* () {
t *L dI () return *LoadImage();
}
ImagePtr image = ImagePtr("anImageFileName");
image->Draw(Point(50, 100));
// (image.operator->())->Draw(Point(50, 100))
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.
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 Proxy
Ejemplo: Un Proxy Virtual
class Graphic {
public: 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;
protected: p
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 Draw(const Point& at);
virtual void HandleMouse(Event& event);
virtual const Point& GetExtent();
virtual void Load(istream& from);
virtual void Save(ostream&to);
78
virtual void Save(ostream& to);
private:
// ...
};
Proxy Proxy
Ejemplo: Un Proxy Virtual
class ImageProxy : public Graphic {// la clase proxy class ImageProxy : public Graphic {// la clase proxy
public:
ImageProxy(const char* imageFile);
virtual ~ImageProxy();
i t l id D ( t P i t& t) virtual void Draw(const Point& at);
virtual void HandleMouse(Event& event);
virtual const Point& GetExtent();
virtual void Load(istream&from); virtual void Load(istream& from);
virtual void Save(ostream& to);
protected:
Image* GetImage();
i t private:
Image* _image;
Point _extent;
char* fileName; c a _ e a e;
};
79
Proxy Proxy
Ejemplo: Un Proxy Virtual
ImageProxy::ImageProxy (const char* fileName) {
const Point& ImageProxy::GetExtent () {
if ( t t P i t Z ) {
ImageProxy::ImageProxy (const char fileName) {
_fileName =strdup(fileName);
_extent =Point::Zero; // don't know extent yet
_image =0;
}
if (_extent ==Point::Zero) {
_extent =GetImage()->GetExtent();
}
return _extent;
}
Image* ImageProxy::GetImage() {
if (_image ==0) {
_image =new Image(_fileName);
}
}
void ImageProxy::Draw (const Point& at) {
GetImage()->Draw(at);
}
}
return _image;
}
}
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 Proxy
Ejemplo: Un Proxy Virtual
class TextDocument {
public:
TextDocument();
void Insert(Graphic*); void Insert(Graphic*);
// ...
};
TextDocument* text = new TextDocument;
// ...
text->Insert(new ImageProxy("anImageFileName"));
81
Ejercicio (Junio de 208)
S l li i d did i t t t i Sea la aplicacin de pedidos vista en temas anteriores:
Ejercicio Ejercicio
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.
Solucin (1)
#i ncl ude " st daf x. h"
#i ncl ude <i ost r eam>
#i ncl ude <st r i ng>
usi ng st d: : cout ; usi ng st d: : cout ;
usi ng st d: : st r i ng;
usi ng st d: : ci n;
cl ass Cuent a
{{
publ i c:
vi r t ual i nt obt ener Di sponi bl e ( ) = 0;
};
cl ass Cuent aReal : publ i c Cuent a cl ass Cuent aReal : publ i c Cuent a
{
pr i vat e:
i nt di sponi bl e;
publ i c: publ i c:
Cuent aReal ( i nt d ) : di sponi bl e ( d) {}
i nt obt ener Di sponi bl e( ) {r et ur n di sponi bl e; }
};
cl ass Pr oxyCuent a: publ i c Cuent a cl ass Pr oxyCuent a: publ i c Cuent a
{
pr i vat e:
Cuent aReal * cuent a;
st r i ng cl ave; st r i ng cl ave;
bool cor r ect a;
bool i nt r o;
publ i c:
Pr oxyCuent a ( st r i ng psswd Cuent aReal & c ) : Pr oxyCuent a ( st r i ng psswd, Cuent aReal & c ) :
cl ave( psswd) , cuent a( &c) , i nt r o( f al se) , cor r ect a( f al se) {}
i nt obt ener Di sponi bl e( ) ;
};
Solucin (2)
i nt Pr oxyCuent a: : obt ener Di sponi bl e( ) {
i f ( cor r ect a) r et ur n cuent a- >obt ener Di sponi bl e( ) ;
el se i f ( ! i nt r o) {
i nt r o = t r ue;
st r i ng cl ;
cout << " I nt r oduce l a cl ave: \ n" ;
ci n >> cl ;
i f ( cl == cl ave) {
cor r ect a = t r ue;
r et ur n cuent a- >obt ener Di sponi bl e( ) ;
}
el se {
cor r ect a = f al se;
cout << " cl ave i ncor r ect a\ n";
r et ur n - 1;
}
}
r et ur n - 1;
}
voi d mai n( )
{
Cuent aReal c ( 100) ;
Pr oxyCuent a pc ( " cl ave1" , c) ;
i nt d = pc. obt ener Di sponi bl e( ) ;
cout << " Di sponi bl e = " << d << " \ n" ;
cout << " Di sponi bl e = " << pc. obt ener Di sponi bl e( ) ;
}
Adapter Adapter
Propsito.
Convierte el interfaz de una clase en otro que espera el cliente. q p
El adapter permite trabajar juntas a clases que de otra forma no podran por
tener interfaces incompatibles.
Tambin conocido como. Tambin conocido como.
Wrapper (envoltorio).
Motivacin.
A veces una clase de una biblioteca que ha sido diseada para reutilizarse A veces una clase de una biblioteca que ha sido diseada para reutilizarse,
no puede hacerlo porque su interfaz no coincide con la interfaz especfica
de dominio que requiere la aplicacin.
Ej : un editor de dibujo Objetos grficos con una clase base abstracta Ej.: un editor de dibujo. Objetos grficos, con una clase base abstracta
Shape.
Queremos reutilizar una clase existente TextView para implementar TextShape
(quiz no tengamos el cdigo fuente de TextView).
Solucin: Definir una clase TextShape que adapte el interfaz de TextView a
Shape.
Se puede hacer de dos maneras:
Adaptador de clase: Heredando el interfaz de Shape y la implementacinde
86
Adaptador de clase: Heredando el interfaz de Shape y la implementacin de
TextView.
Adaptador de objeto: Componiendo un objeto TextView dentro de un TextShape, e
implementando TextShape en trminos de la interfaz de TextView.
Adapter Adapter
Motivacin.
Adaptador de objeto. p j
87
Adapter Adapter
Estructura.
Adaptador de clase. p
88
Adapter Adapter
Estructura.
Adaptador de objeto. p j
89
Indice Indice
Introduccin.
Patrones de Creacin.
Patrones Estructurales.
Patrones de Comportamiento Patrones de Comportamiento.
Iterator.
Observer.
Template Method.
State.
Strategy. gy
Command.
Chain of Responsibility
90 90 90
Chain of Responsibility.
Conclusiones.
Bibliografa.
Patrones de Comportamiento Patrones de Comportamiento
Tratan sobre algoritmos y la asignacin de
responsabilidades entre objetos. p j
Describen no slo patrones de clases y
objetos sino patrones de comunicacin objetos, sino patrones de comunicacin
entre ellos.
Caracterizan un flujo de control complejo,
difcil de seguir en tiempo de ejecucin. difcil de seguir en tiempo de ejecucin.
Permiten que el diseador se concentre
l i t t bj t slo en cmo interconectar objetos.
Iterator Iterator
Propsito Propsito.
Proporciona un medio de acceder a los elementos de un
contenedor secuencialmente sin exponer su representacin
interna interna.
Tambin Conocido Como.
Cursor.
Motivacin.
Un contenedor (p.ej.: una lista) debe proporcionar un medio de
navegar sus datos secuencialmente sin exponer su g p
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.
92
Dar la responsabilidad de acceder y recorrer el objeto lista a un
objeto Iterator.
Iterator Iterator
Motivacin.
List ListIterator
1 *
list
+ Count()
+ Append(Element)
+ Remove(Element)
+ First()
+Next()
- index
1 *
+ 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 elementos de la lista secuencialmente.
Separar el mecanismo de recorrido del objeto lista, nos permite
definir iteradores que implementen distintas estrategias.
93
Iterator Iterator
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()
A d(El t)
Iterator
+ First()
+ Next()
Cli t
+ Append(Element)
+ Remove(Element)

Next()
+ IsDone()
+ CurrentItem()
Client
1
*
list
List SkipList ListIterator SkipListIterator
1
skiplist
*
Podemos hacer responsables a las listas de crear sus propios iteradores, mediante un factory
94
method (CreateIterator).
Se puede definir algoritmos generales que usan un iterador genrico (en C++: for_each, find_if,
count, etc)
Iterator Iterator
Aplicabilidad. Usar el patrn :
para acceder al contenido de un contenedor sin exponer su 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).
Estructura.
Iterator
Aggregate
+CreateIterator ()
Iterator
+First ()
+Next ()
+IsDone ()
Client
IsDone ()
+CurrentItem ()
ConcreteAggregate
+CreateIterator ()
ConcreteIterator
95
return new ConcreteIterator (this)
Iterator Iterator
Participantes Participantes.
Iterator.
Define una interfaz para recorrer los elementos y acceder a ellos.
ConcreteIterator.
Implementa la interfaz Iterator.
Mantiene la posicin actual en el recorrido del agregado.
Aggregate.
Define una interfaz para crear un objeto Iterator.
ConcreteAggregate.
Implementa una interfaz de creacin del Iterator para devolver una
instancia del ConcreteIterator apropiado.
Colaboraciones.
Un ConcreteIterator sabe cul es el objeto actual del agregado y
puede calcular el objeto siguiente del recorrido.
96
Iterator Iterator
Consecuencias 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.
Implementacin. Implementacin.
Quin controla la iteracin?.
El cliente controla la iteracin: iterador externo.
El iterador controla la iteracin: iterador interno El iterador controla la iteracin: iterador interno.
Quin define el algoritmo de recorrido?
El iterador.
El d l it d l l l t d d l El agregado, y el iterador slo almacena el estado de la
iteracin. A este tipo de iterador se le llama cursor.
Cmo de robusto es el iterador?
Iterador robusto: Las inserciones y borrados no interfieren en el
97
Iterador robusto: Las inserciones y borrados no interfieren en el
recorrido (y se hace sin copiar el agregado).
Iterator Iterator
I l t i Implementacin.
Operaciones adicionales del iterador.
Por ejemplo, iteradores ordenados podran tener una operacin Por ejemplo, iteradores ordenados podran tener una operacin
Previous. Otras como SkipTo.
Usar iteradores polimrficos en C++.
Los iteradores polimrficos han de crearse dinmicamente por un Los iteradores polimrficos han de crearse dinmicamente por un
mtodo de fabricacin.
El cliente adems es responsable de borrarlos (propenso a
errores) errores).
Iteradores para Composites.
Los iteradores externos pueden ser complicados de implementar
t t i en estructuras recursivas.
NullIterators.
Es un iterador degenerado que ayuda a manejar condiciones
98
g q y j
lmite.
Iterator
1 Interfaces de la lista y el iterador
Iterator
Ejemplo
1. Interfaces de la lista y el iterador.
template <class Item>
class List {
public: public:
List(long size = DEFAULT_LIST_CAPACITY);
long Count() const;
Item& Get(long index) const;
// ...
};
template <class Item> 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:
99
protected:
Iterator();
};
Iterator
2 Implementaciones de las subclases del iterador
Iterator
Ejemplo
2. Implementaciones de las subclases del iterador.
template <class Item>
class ListIterator : public Iterator<Item> {
public: 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; const List<Item> _list;
long _current;
};
template <class Item> template <class Item>
Item ListIterator<Item>::CurrentItem () const {
if (IsDone()) throw IteratorOutOfBounds;
return _list->Get(_current);
100
}
// Se puede implementar un ReverseListIterator, con First
// posicionando el iterador al final de la lista, y Next decrementando
Iterator
3 U d l i d
Iterator
Ejemplo
3. Uso del iterador.
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 Iterator
Ejemplo
4. Evitar ajustarse a una implementacin concreta de la lista. j p
Supongamos que tenemos SkipList y SkipListIterator.
Se puede introducir un AbstractList para estandarizar la interfaz de la lista
(List y SkipList son subclases de AbstractList). ( y p )
Para permitir iteracin polimrfica, AbstractList define un factory method
CreateIterator.
template <class Item> 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 that we have an AbstractList y
AbstractList<Employee*>* employees;
// ...
Iterator<Employee*>* iterator = employees->CreateIterator();
P i tE l (*it t )
102
PrintEmployees(*iterator);
delete iterator;
Iterator Iterator
Ejemplo
5. Asegurarse de que los iteradores se borran. g q
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) {} IteratorPtr(Iterator<Item>* i): _i(i) {}
~IteratorPtr() {delete _i; }
Iterator<Item>* operator->() {return _i; }
Iterator<Item>& operator*() {return *_i; }
AbstractList<Employee*>* employees;
// ...
I P E l *
p () { _ }
private:
// disallow copy and assignment to avoid
// multiple deletions of _i:
IteratorPtr(const IteratorPtr&);
IteratorPtr<Employee*>
iterator(employees->CreateIterator());
PrintEmployees(*iterator);
IteratorPtr(const IteratorPtr&);
IteratorPtr& operator=(const IteratorPtr&);
private:
Iterator<Item>* _i;
103
_
};
Iterator
6. Un iterador interno.
Iterator
Ejemplo
El iterador controla la iteracin, y aplica una operacin a cada elemento.
La operacin se puede configurar:
Pasando un puntero a una funcin o a un objeto funcin Pasando un puntero a una funcin, o a un objeto funcin.
Mediante subclasificacin.
template <class Item>
class ListTraverser {
public:
ListTraverser(List<Item>* aList):_iterator(aList) {};
template <class Item>
bool ListTraverser<Item>::Traverse () {
bool result =false;
for ( iterator First(); ! iterator IsDone(); iterator Next()) {
bool Traverse();
protected:
virtual bool ProcessItem(const Item&) =0;
private:
for ( _iterator.First(); !_iterator.IsDone();_iterator.Next()) {
result =ProcessItem(_iterator.CurrentItem());
if (result ==false) break;
}
returnresult;
ListIterator<Item>_iterator;
};
return result;
}
104
Iterator
6 U i d i
Iterator
Ejemplo
6. Un iterador interno
Imprimir los n primeros empleados de una lista.
class PrintNEmployees : public ListTraverser<Employee*>{ 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: private:
int _total;
int _count;
}; }
bool PrintNEmployees::ProcessItem (Employee* const& e) {
_count++;
e >Print();
105
e->Print();
return _count < _total;
}
Iterator
6 U it d i t
Iterator
Ejemplo
List<Employee*>* employees;
6. Un iterador interno
Imprimir los n primeros empleados de una lista.
List Employee employees;
// ...
PrintNEmployees pa(employees, 10);
pa.Traverse();
Comparacin con un iterador externo:
ListIterator<Employee*> i(employees);
int count =0; int count = 0;
for (i.First(); !i.IsDone(); i.Next()) {
count++;
i.CurrentItem()->Print();
if (count >= 10) break;
}
106
Iterator
6 U i d i
Iterator
Ejemplo
6. Un iterador interno
Pueden encapsular distintos tipos de operaciones.
template <class Item> template <class Item>
class FilteringListTraverser {
public:
FilteringListTraverser(List<Item>* aList);
()
template <class Item>
void FilteringListTraverser<Item>::Traverse () {
bool result =false;
for (_iterator.First();!_iterator.IsDone();_iterator.Next()) {
bool Traverse();
protected:
virtual bool ProcessItem(const Item&) =0;
virtual bool TestItem(const Item&) =0;
(_ () _ () _ ()) {
if (TestItem(_iterator.CurrentItem())) {
result =ProcessItem(_iterator.CurrentItem());
if (result ==false) break;
}
( )
private:
ListIterator<Item>_iterator;
};
}
}
return result;
}
107
Observer Observer
P it Propsito.
Define una dependencia de uno-a-muchos entre objetos, de
forma que cuando un objeto cambie de estado se notifique y q j q y
actualicen automticamente todos los objetos que dependen
de l.
Tambin conocido como Tambin conocido como.
Dependents, Publish-Subscribe
Motivacin.
Mantener consistencia entre objetos relacionados.
No queremos obtener dicha consistencia aumentando el
acoplamiento entre clases acoplamiento entre clases.
Ej.: separacin de la presentacin en GUI de los datos de
aplicacin subyacente.
108
Observer Observer
Motivacin.
40
A
C
D
10
20
30
40
A B C D
X 60 20 15 5
Y 40 25 15 20
B
0
A B C D
Y 40 25 15 20
Z 10 10 20 60
Modelo
A: 40%
B: 25%
C 15%
109
C: 15%
D: 20%
Observer Observer
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 que cambiar. y q
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) que los objetos estn fuertemente acoplados).
Estructura.
Subject Observer
observers
1 * 0 1
+Attach (Observer)
+Detach (Observer)
+Notify ()
+Update()
forall o in observers
o.Update()
1..* 0..1
o.Update()
ConcreteSubject
ConcreteObserver
- observerState
subject
0..1
110
+GetState ()
+SetState ()
- subjectState
+Update ()
subject
return subjectState observerState=
subject->GetState()
Observer Observer
Participantes.
S bj t Subject.
Conoce a sus observadores, que pueden ser un nmero arbitrario.
Proporciona un interfaz para aadir y quitar objetos Observer.
Ob Observer.
Define un interfaz de actualizacin para los objetos que deben ser
notificados sobre cambios en un sujeto.
ConcreteSubject ConcreteSubject.
Almacena estado de inters para ConcreteObservers.
Manda notificaciones a sus observadores cuando su estado cambia.
ConcreteObserver ConcreteObserver.
Mantiene una referencia a objetos ConcreteSubject.
Almacena el estado que debe ser consistente con el del sujeto.
Implementa el interfaz de actualizacin del Observer para mantener su Implementa el interfaz de actualizacin del Observer para mantener su
estado consistente con el del sujeto.
111
Observer Observer
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
barDiagram
:ConcreteObserver
sectorDiagram
:ConcreteObserver
SetState()
Notify()
Update()
GetState() GetState()
Update()
GetState()
112
Observer Observer
Consecuencias Consecuencias.
Permite modificar los sujetos y observadores de manera
independiente.
S d tili l j t i b d Se pueden reutilizar los sujetos sin sus observadores 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) es mnimo).
Capacidad de comunicacin mediante difusin. La notificacin
del sujeto se enva automticamente a todos los observadores
suscritos. Se pueden aadir y quitar observadores en cualquier p y q q
momento.
Actualizaciones inesperadas. Una operacin aparentemente
inofensiva sobre el sujeto puede desencadenar una cascada de
bi l b d
113
cambios en los observadores.
Observer Observer
Implementacin Implementacin.
Correspondencia entre sujetos y observadores.
Que el sujeto guarde referencias a los observadores a los que debe
notificar notificar.
Observar ms de un sujeto.
Ej.: una hoja de clculo puede observar ms de un origen de datos.
Extender la interfaz de actualizacin para que el observador sepa 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()).
Quin dispara la actualizacin? Q p
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.
Los clientes llaman a Notify():
Ventaja: se puede optimizar llamando a notify slo despus de varios
cambios.
Inconveniente: los clientes tienen la responsabilidadaadida de llamar
114
Inconveniente: los clientes tienen la responsabilidad aadida de llamar
a Notify().
Observer Observer
Implementacin.
Referencias perdidas a sujetos borrados.
Una manera de evitarlo es notificar a los observadores
cuando se borra un sujeto.
Asegurarse de que el estado del Sujeto sea consistente Asegurarse de que el estado del Sujeto sea consistente
consigo mismo antes de la notificacin:
Hay que tener cuidado con las operaciones heredadas. Hay que tener cuidado con las operaciones heredadas.
void MySubject::Operation (int newValue) {
BaseClassSubject::Operation(newValue); BaseClassSubject::Operation(newValue);
// trigger notification
_myInstVar += newValue;
// update subclass state (too late!)
}
115
}
Observer Observer
Implementacin Implementacin.
Evitar protocolos especficos del obervador: los modelos
push y pull.
Las implementaciones de observer suelen hacer que el sujeto
envie informacin adicional como parmetro de Update().
Dos extremos:
Modelo Push: el sujeto enva informacin detalla del cambio quieran Modelo Push: el sujeto enva informacin detalla del cambio, quieran
los observadores o no.
Inconveniente: observadores menos reutilizables.
Modelo Pull: el sujeto no enva nada, y los observadores piden
d l d t ll l it t despus los detalles explcitamente.
Inconveniente: puede ser poco eficiente.
Especificar las modificaciones de inters explcitamente:
Mejorar la eficiencia haciendo que los observadores registren Mejorar la eficiencia haciendo que los observadores registren
solo aquellos eventos que les interesen.
Los observadores se subscriben a aspectos del sujeto.
116
Observer Observer
Implementacin.
Encapsular la semntica de las operaciones complejas Encapsular la semntica de las operaciones complejas.
Si la relacin de dependencia entre sujetos y observadores es compleja, puede ser
necesario un objeto intermedio para la gestin de cambios (ChangeManager).
Minimizar el trabajo necesario para que los observadores reflejen los cambios en el j p q j
sujeto.
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)
Observer
+Update(Subject)
subjects
1..* 0..*
ChangeManager
chman
1
Subject-Observer mapping
observers
+Attach (Observer o)
+Detach (Observer)
+Notify ()
+Update(Subject)
+Register (Subject,Observer)
+Unregister (Subject,Observer)
+Notify ()
chman->Notify()
Marcar todos los observers
a actualizar.
Actualizar los observers
chman >Notify()
chman->Registar(this,o)
SimpleChangeManager DAGChangeManager
Actualizar los observers
marcados.
117
+Register (Subject,Observer)
+Unregister (Subject,Observer)
+Notify ()
+Register (Subject,Observer)
+Unregister (Subject,Observer)
+Notify ()
forall s in subjects:
forall o in observers:
o->Update(s)
Observer Observer
Ejemplo
class Subject;
class Subject {
public:
virtual ~Subject();
class Subject;
class Observer {
public:
virtual ~ Observer();
j ()
virtual void Attach(Observer*);
virtual void Detach(Observer*);
virtual void Notify();
protected:
()
virtual void Update (Subject*
theChangedSubject) = 0;
// soporte de mltiples subjects
protected:
protected:
Subject();
private:
List<Observer*> *_observers;
protected:
Observer();
};
_
};
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);
118
i.CurrentItem()->Update(this);
}
}
Observer Observer
Ejemplo
class ClockTimer : public Subject {
class DigitalClock: public Widget, public
class ClockTimer : public Subject {
// Concrete subject
public:
ClockTimer();
class DigitalClock: public Widget, public
Observer {
public:
DigitalClock(ClockTimer*);
i t l Di it lCl k()
()
virtual int GetHour();
virtual int GetMinute();
virtual int GetSecond();
voidTick();
virtual ~DigitalClock();
virtual void Update(Subject*);
// overrides Observer operation
virtual void Draw();
void Tick();
};
void ClockTimer::Tick () {
virtual void Draw();
// overrides Widget operation;
// defines how to draw the digital clock
private:
Cl kTi * bj t
// update internal time-keeping state
// ...
Notify();
}
ClockTimer* _subject;
};
DigitalClock::DigitalClock (ClockTimer* s) {
bj t
}
_subject = s;
_subject->Attach(this);
}
DigitalClock::~DigitalClock () {
119
DigitalClock:: DigitalClock () {
_subject->Detach(this);
}
Observer Observer
Ejemplo
void DigitalClock::Update (Subject* theChangedSubject) {
if (theChangedSubject == _subject) Draw();
}
void DigitalClock::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 public Observer { class AnalogClock : public Widget, public Observer {
public:
AnalogClock(ClockTimer*);
virtual void Update(Subject*);
virtual void Draw();
// ...
};
120
ClockTimer* timer = new ClockTimer;
AnalogClock* analogClock = new AnalogClock(timer);
DigitalClock* digitalClock = new DigitalClock(timer);
Observer
Sistemas de eventos en J ava (observer listener)
Observer
Usos Conocidos
Sistemas de eventos en J ava (observer=listener)
AWT/Swing
J avabeans
MVC en el sistema de ventanas de Smalltalk
Model=Subject
View=Observer View=Observer
Controller=Cualquier objeto que cambie el estado de Subject
MVC en entornos web (J 2EE)
Model=EJ B
View=J SP
Controller=servlet Controller servlet
121
Template Method Template Method
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 Permite que las subclases cambien pasos de un algoritmo sin cambiar
su estructura.
Motivacin.
Ej.: MFCs, abrir un fichero.
Document Application
docs
1 *
void Application::OpenDocument (const char* name) {
if (!CanOpenDocument(name)) {
// cannot handle this document
+Abrir()
+Cerrar()
+Guardar()
D R d()
pp
+AddDocument()
+OpenDocument()
+DoCreateDocument()
+CanOpenDocument()
1..*
// cannot handle this document
return;
}
Document* doc =DoCreateDocument();
if (doc) {
+DoRead()
+CanOpenDocument()
+AboutToOpenDocument()
MyDocument
MyApplication
if (doc) {
_docs->AddDocument(doc);
AboutToOpenDocument(doc);
doc->Open();
doc >DoRead();
122
y
+DoCreateDocument()
+CanOpenDocument()
+AboutToOpenDocument()
+DoRead()
return MyDocument
doc->DoRead();
}
}
Template Method
Aplicabilidad.
Template Method
Para implementar las partes de un algoritmo que no cambian,
y dejar que las subclases implementen el comportamiento
que puede variar que puede 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.
E t t Estructura.
ClaseAbstracta
+TemplateMethod()
+PrimitiveOperation1()

+PrimitiveOperation2()
+

PrimitiveOperation1()

PrimitiveOperation2()
123
ConcreteClass
+PrimitiveOperation1()
+PrimitiveOperation2()
State State
Propsito.
Permitir que un objeto modifique su comportamiento cada vez que cambie su Permitir que un objeto modifique su comportamiento cada vez que cambie su
estado interno.
Parecer que cambia la clase del objeto.
Tambin conocido como.
Objets for state (estados como objetos).
Motivacin.
TCPConnection para representar una conexin de red. p p
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 State
Estructura.
125
Strategy Strategy
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.
Tambin conocido como.
Policy (poltica).
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 encapsulado se denomina estrategia.
126
Strategy Strategy
Estructura.
127
Command Command
Propsito.
Encapsula peticiones a objetos Encapsula peticiones a objetos.
Permite parametrizar a los clientes con diferentes peticiones, hacer
cola o llevar un registro de peticiones, as como deshacer las
peticiones peticiones.
Tambin conocido como.
Action, Transaction.
M ti i Motivacin.
Framework grfico tipo MFC. Peticiones de los distintos widgets
encapsuladas como objetos.
128
Command Command
M ti i Motivacin.
129
Command Command
E t t Estructura.
130
Chain of Resposibility Chain of Resposibility
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 Encadena los objetos receptores y pasa la peticin a travs de la
cadena hasta que es procesada por algn objeto.
Motivacin.
Ej.: ayuda sensible al contexto en una GUI.
Si no existe ayuda para una parte de la interfaz, se muestra ayuda
para una parte ms general. p p g
131
Chain of Resposibility Chain of Resposibility
Motivacin.
132
Chain of Resposibility Chain of Resposibility
Estructura.
133
Indice Indice
I t d i Introduccin.
Patrones de Creacin.
Patrones Estructurales Patrones Estructurales.
Patrones de Comportamiento.
Conclusiones Conclusiones.
Bibliografa.
134 134 134
Conclusiones Conclusiones
Los patrones de diseo capturan el conocimiento que Los patrones de diseo capturan el conocimiento que
tienen los expertos a la hora de disear.
Los patrones ayudan a generar software maleable
(software que soporta y facilita el cambio, la reutilizacin
y la mejora) y la mejora).
Los patrones de diseo son guas, no reglas rigurosas.
Cada patrn describe la solucin a problemas que se
repiten una y orta vez en nuestro entorno de forma que repiten una y orta vez en nuestro entorno, de forma que
se puede usar esa solucin todas las veces que haga
falta.
135
Indice Indice
I t d i Introduccin.
Patrones de Creacin.
Patrones Estructurales Patrones Estructurales.
Patrones de Comportamiento.
Conclusiones Conclusiones.
Bibliografa.
136 136 136
Bibliografa Bibliografa
D i tt l t f bl bj t Design patterns, elements of reusable object-
oriented software. Gamma, Helm, J onhnson,
Vlissides Addison Wesley 1995 (traducido al Vlissides. Addison Wesley, 1995 (traducido al
espaol en 2003).
Applying UML and Patterns. An introduction to
Object Oriented Analysis and Design and Object-Oriented Analysis and Design and
Iterative Development. 3rd Edition. Craig
Larman Prentice Hall 2005 Larman. Prentice Hall.2005.
http://hillside net/
137 137 137
http://hillside.net/

También podría gustarte