137
Patrones de Diseño Tema 7 TACC II Grupo 46 1 TACC II Curso 2008/09

Patrones Libre

Embed Size (px)

DESCRIPTION

Descripción de patrones de diseño de software Uso de patrones

Citation preview

Page 1: Patrones Libre

Patrones de Diseño

Tema 7

TACC II

Grupo 46

111

TACC IICurso 2008/09

Page 2: Patrones Libre

IndiceIndice

I t d i ó” Introducc ión.» Patrones.» Descripción de los Patrones.» Ejemplo: Patrones en el MVC de Smalltalk.» El catálogo de patrones.

” Patrones de Creación.” Patrones Estructurales.” Patrones de Comportamiento.” C l i” Conclusiones.” Bibliografía.

222

Page 3: Patrones Libre

IntroducciónIntroducción

” Di ñ ífi l bl l” Diseño específico para el problema, pero general como para poder adecuarse a futuros requisitos y problemas.

” Evitar el rediseño 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 comunicación entre objetos en muchas soluciones de diseño.

3

Page 4: Patrones Libre

PatrónPatrón

” 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: “héroe trágico”, “comedia romántica”, etc.» Arte.» Ingenierías.» Arquitectura.

” Christopher Alexander. “A Pattern Language: Towns, Buildings, p g g , g ,Construction”. 1977.

” http://www.patternlanguage.com

4

Page 5: Patrones Libre

Patrones de DiseñoPatrones de Diseño

” R tili di ñ b t t i l d t ll” Reutilizar diseños abstractos que no incluyan detalles de la implementación.

” Un patrón es una descripción del problema y la esencia de su solución, que se puede reutilizar en casos q pdistintos.

E l ió d d bl ú” Es una solución adecuada a un problema común.

” A i d i t ió bj t l i i i” Asociado a orientación a objetos, pero el principio general es aplicable a todos los enfoques de diseño software.

5

Page 6: Patrones Libre

Patrones de Diseño

”D t l i i l di ñ

Patrones de Diseño

”Documentar la experiencia en el diseño, en forma de un catálogo de patrones.

”Categorías de patrones:

» De creación : implica el proceso de instanciar objetos.

» Estructurales : composición de objetos.

» De comportamiento cómo se com nican los objetos» De comportamiento : cómo se comunican los objetos, cooperan y distribuyen las responsabilidades para lograr sus objetivos.

6

Page 7: Patrones Libre

Patrones de DiseñoEstructura de un patrón

” N b d l t ó” Nombre del patrón.» Describe el problema de diseño, junto con sus soluciones y

consecuencias. » V b l i d di ñ» Vocabulario de diseño.

” Problema.» Describe cuándo aplicar el patrón. » Explica el problema y su contexto.

” Solución.» Elementos que forman el diseño, relaciones, responsabilidades.» Elementos que forman el diseño, relaciones, responsabilidades.» No un diseño concreto, sino una plantilla que puede aplicarse en

muchas situaciones distintas.

” Consecuencias” Consecuencias .» Resultados, ventajas e inconvenientes de aplicar el patrón.» P.ej.: relación entre eficiencia en espacio y tiempo; cuestiones de

implementación etc

7

implementación, etc.

Page 8: Patrones Libre

Patrones de DiseñoEjemplo: 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 20B 0

A B C D

Y 40 25 15 20

Z 10 10 20 60

ModeloA: 40%B: 25%C 15%

8

C: 15%D: 20%

Page 9: Patrones Libre

Patrones de Diseño

” 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 pflexibilidad y reutilización.

D l i d d l di l d” Desacoplar vistas de modelos, mediante un protocolo de subscripción/notificación.

” Cada vez que cambian los datos del modelo, avisar a las vistas que dependen de él. Estas se actualizan.

9

q p

Page 10: Patrones Libre

Patrones de Diseño

” Patrón Observer más general (dependencias entre

Ejemplo: MVC de Smalltalk

” Patrón Observer, más general (dependencias entre objetos).

” Las vistas se pueden anidar: Vistas compuestas y simples.» Generalización: Patrón Composite» Generalización: Patrón Composite.

” La relación entre la vista y el controlador: patrón 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: Añade capacidad de desplazamiento a una vista

10

» Decorator: Añade capacidad de desplazamiento a una vista.

Page 11: Patrones Libre

El catálogo de patronesEl catálogo de patronesPropósito

Creación Estructurales De Comportamiento

Clase Factory Method Adapter (de clases) Interpreter.Template MethodTemplate Method.

Ám Objeto Abstract Factory Adapter (de objetos). Chain of Responsibility.m

bito

jBuilderPrototypeSingleton

Bridge.Composite.Decorator.

Command.Iterator.Mediator.

Facade.Flyweight.Proxy.

Memento.Observer.State.

11

Proxy. State.Strategy.Visitor.

Page 12: Patrones Libre

El catálogo de patronesRelaciones entre

los patrones.

12

Page 13: Patrones Libre

IndiceIndice

” Introducción” Introducción.” Patrones de Creación.

»Singleton»Singleton .»Abstract Factory.»Factory Method.

” Patrones Estructurales.” Patrones de Comportamiento.” Concl siones” Conclusiones.” Bibliografía.

131313

Page 14: Patrones Libre

Patrones de CreaciónPatrones de Creación

” Ab t l d i t i ió” Abstraen el proceso de instanciación” Ayudan a que el sistema sea independiente de

cómo se crean componen y representan loscómo se crean, componen y representan los objetos.

” Flexibilizan:Flexibilizan:» qué se crea» quién lo crea» cómo se crea» cuándo se crea

” Permiten configurar un sistema:” Permiten configurar un sistema:» estáticamente (compile-time)» dinámicamente (run-time)

14

( )

Page 15: Patrones Libre

SingletonSingleton

” I t ió” Intenc ión.» Asegurar que una clase tiene una única instancia y proporciona un

punto de acceso global a dicha instancia.

” Motivación.» 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 impresión” Un único sistema de ficherosUn único sistema de ficheros” Un único fichero de log, o un único repositorio.

»¿Cómo asegurarlo? una variable global hace el objeto accesible pero se puede instanciar varias vecesaccesible, pero se puede instanciar varias veces.

»Responsabilidad de la clase misma: actuar sobre el mensaje de creación de instancias

15

Page 16: Patrones Libre

SingletonSingleton

” 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

subclasificación, y los clientes deben ser capaces de usar unainstancia extendida sin modificar su códigoinstancia extendida sin modificar su código.

” Estructura.

Singleton

static Singleton uniqueInstancesingletonData

static Singleton Instance ()SingletonOperation ()GetSingletonData ()

return uniqueInstance

16

Page 17: Patrones Libre

SingletonSingleton” Partici pantes:p

» Singleton:” Define una operación 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 través de la

operación “Instance”.” 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 representación. Se puedep y p p

subclasificar de la clase Singleton y configurar la aplicación con unainstancia de esta clase.

» Fácil modificación para permitir un número variable de instancias.

17

» Más flexible que las operaciones de clase.

Page 18: Patrones Libre

SingletonSingleton

” Implementación:” Implementación: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 = new Singleton;18

_instance = new Singleton;return _instance;

}

Page 19: Patrones Libre

Ejemplo#include "stdafx.h"#include <iostream>using namespace std; Ejemploclass Maze{

int x, y;public:

M (i i ) ( ) ( ) {}Maze(int x, int y) : x(x), y(y) {}};

class MazeFactory {blipublic:

static MazeFactory* Instance();// existing interface goes hereMaze * createMaze(int x, int y) { return new Maze(x, y); };

t t dprotected: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;

}

19void main(){

Maze * m = MazeFactory::Instance()->createMaze(10,10);}

Page 20: Patrones Libre

Singleton” Implementación:

» Creación de una subclase de singleton.» D t i é i l t l ió “I t ”» Determinar qué singleton queremos usar en la operación “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; }

Page 21: Patrones Libre

SingletonSingleton

” ¿Dónde 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

Page 22: Patrones Libre

SingletongEjemplo

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 tg g

protected:MazeFactory();

private:static MazeFactory* instance;

_instance = new BombedMazeFactory;} else if (strcmp(mazeStyle, "enchanted") == 0)

_instance = new EnchantedMazeFactory;// ... other possible subclassesstatic MazeFactory _instance;

};

MazeFactory* MazeFactory::_instance = 0;

} else_instance = new MazeFactory;

return _instance;}}

22

Page 23: Patrones Libre

Abstract FactoryAbstract Factory

” P ó it” Prop ósito.»Proporciona una interfaz para crear familias de objetos

relacionados o que dependen entre sí, sin especificar suslclases concretas.

” También Conocido Como.» Kit» Kit.”Motivación.» Ej.: un framework para la construcción de interfaces de usuario

“ f ” ( fque permita varios “look and feel” (ej.: Motif y PresentationManager).”Una clase abstracta WidgetFactory con la interfaz para crear

cada tipo de widgetcada 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 lookand feel concreto.

Page 24: Patrones Libre

Abstract FactoryAbstract Factory

” Motivación.

WidgetFactory

CreateScrollBar()CreateWindow()

Client

Window

Productos

MotifWidgetFactory PMWindowFactoryMotifWindowPMWindow

Familias

MotifWidgetFactory

CreateScrollBar()CreateWindow()

PMWindowFactory

CreateScrollBar()CreateWindow()

ScrollBar

MotifScrollBarPMScrollBar

24

Page 25: Patrones Libre

Abstract FactoryAbstract Factory

” Aplicabilidad. Usar este patrón cuando:»un sistema que deba ser independiente de cómo se

dcrean, componen y representan sus productos.»un sistema que deba ser configurado con una familia de

productos entre variasproductos entre varias.»una familia de objetos producto relacionados que está

diseñada para ser usada conjuntamente y es necesariodiseñada para ser usada conjuntamente, y es necesariohacer cumplir esta restricción.

»se quiere proporcionar una biblioteca de clasesq p pproductos, y sólo se quiere revelar sus interfaces, no suimplementación.

25

Page 26: Patrones Libre

Abstract FactoryAbstract Factory

”Estructura:

AbstractFactory

createProductA ()

ClientProductos()

createProductB () AbstractProductA

Familias

ConcreteFactory1

createProductA ()createProductB ()

ConcreteFactory2

createProductA ()createProductB ()

AbstractProductB

ProductA1ProductA2

createProductB () createProductB ()

ProductB1ProductB2

26

Page 27: Patrones Libre

Abstract FactoryAbstract Factory” Partici pantes:p

» AbstractFactory. Declara una interfaz para operaciones quecrean objetos producto abstractos.

» ConcreteFactor y. Implementa las operaciones para crear objetosy p p p jproducto concretos.

» AbstractProduct . Declara una interfaz para un tipo de objetoproducto.

» ConcreteProduct . Define un objeto producto para que sea creadopor la fábrica correspondiente.

» Client . Sólo usa interfaces declaradas por las clasesAb t tF t Ab t tP d tAbstractFactory y AbstractProduct.

” Colaboraciones.» Normalmente sólo se crea una única instancia de una clase

ConcreteFactory en tiempo de ejecución. Esta fábrica concretacrea objetos producto que tienen una determinadaimplementación.

» Ab t tF t d l l ió d bj t d t27

» AbstractFactory delega la creación de objetos producto en susubclase ConcreteFactory.

Page 28: Patrones Libre

Abstract Factory

C i

Abstract Factory

”Consecuenc ias.»Aísla las clases concretas. Ayuda a controlar

las clases de objetos que crea una aplicación.Aísla a los clientes de las clases deimplementaciónimplementación.

»Facilita el reemplazo de familias de productos.»P l i t i t d t (»Promueve la consistencia entre productos (que

la aplicación use objetos de una sola familia ala vez)la vez).

»Es difícil añadir un nuevo producto.

28

Page 29: Patrones Libre

Abstract FactoryAbstract FactoryEjemplo

Ejemplo: aplicación para construir un coche a partirde unas partes (motor, chasis, ...)

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

Car

ToyotaCarFordCar PorscheCarCarPart

CarBodyCarEngine

29ToyotaBodyFordBody PorscheBodyToyotaEngineFordEngine PorscheEngine

Page 30: Patrones Libre

Abstract FactoryAbstract FactoryEjemplo (ii)

¿Cómo lo haríamos sin utilizar el patrón Abstract Factory? ¿Cómo lo haríamos sin utilizar el patrón Abstract Factory?En un método del cliente:

CrearCoche (string marca) {

if (marca == “ford”)FordCar coche = new FordCar ()

El código del cliente decide qué clase de coche construir (bien)else if (marca == “toyota”)

ToyotaCar coche = new ToyotaCar ()else …;

coche construir (bien) y qué subpartesinstanciar (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 familiaselse …;

coche.add (motor);...

distintas familias.

30return coche;

}

Page 31: Patrones Libre

Abstract FactoryAbstract FactoryEjemplo (iii)

CarPartFactory

makeCar ()makeBody ()

Client

CarBody

Productosy ()

makeEngine ()CarBody

ToyotaBodyFordBodyFamilias

ToyotaFactory

makeCar ()

FordFactory

makeCar ()

CarEngine

makeCar ()makeBody ()makeEngine ()

makeCar ()makeBody ()makeEngine () ToyotaEngineFordEngine

Car

31

ToyotaCarFordCar

Page 32: Patrones Libre

Abstract FactoryAbstract FactoryEjemplo (iv)

Utilizando el patrón, éste fuerza a que todos los productos sean de lamisma familia, una vez establecida ésta por el cliente.

El patrón permite separar la elección de la familia (la marca delcoche) del proceso de instanciar las partes.

En el cliente:

Car hacerCoche () {Car coche=familia.makeCar();coche.addEngine (familia.makeEngine());coche.addBody (familia.makeBody ());...

t h32

return coche;}

Page 33: Patrones Libre

Abstract Factory

familia contiene una instancia de una marca de coche

Abstract FactoryEjemplo (v)

familia contiene una instancia de una marca de coche. ¿Cómo se instancia familia?

class CrearCoche {CarPartFactory * familia;y ;

Car hacerCoche () {Car coche=familia->makeCar();coche.addEngine (familia->makeEngine());

//presenta por pantalla la selecciónclass CrearCocheGUI : public CFrameWnd {//….

id O 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;

}}

}}

Page 34: Patrones Libre

Abstract FactoryAbstract FactoryOtro Ejemplo: Laberinto

MazeFactory

+MakeMaze(): Maze

MazeGame

+CreateMaze(MazeFactory): Maze+MakeWall(): Wall+MakeRoom(int n): Room+MakeDoor(Room r1, Room r2): Door

Maze Wall RoomEnchantedMazeFactory

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

EnchantedRoom

BombedWall

DoorBombedMazeFactory

RoomWithABomb

34DoorNeedingSpell

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

Page 35: Patrones Libre

Abstract FactoryAbstract FactoryOtro Ejemplo: Laberinto

class MazeFactory {public:

MazeFactory();i t l M * M k M () tvirtual 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

Page 36: Patrones Libre

Abstract FactoryAbstract FactoryOtro 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

}

Page 37: Patrones Libre

Abstract FactoryAbstract FactoryOtro Ejemplo

class EnchantedMazeFactory : public MazeFactory {public:

EnchantedMazeFactory();virtual Room* MakeRoom(int n) constvirtual 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);}

Page 38: Patrones Libre

Factory MethodFactory Method

” P ó it” Prop ósito.»Define una interfaz para crear un objeto, pero deja que

sean las subclases quienes decidan qué clase instanciar.q qPermite que una clase delegue en sus subclases lacreación de objetos.

” También Conocido Como .” También Conocido Como .»Virtual Constructor.

”Motivación.»Ej.: un framework que pueda presentar distintos tipos de

documentos (similar a MFCs).”Dos abstracciones clave: aplicación y documento (ambasp y (

clases abstractas). Hay que subclasificarlas.”La clase aplicación no sabe qué subclase documento

instanciar.

38

Page 39: Patrones Libre

Factory MethodFactory Method

”Motivación.Se le llama “factory method” (métodode fabricación)

Documento

+Abrir()

Aplicacion

+CrearDocumento()

docs1..*

Documento * doc = CrearDocumento()d h b k(d )

b ()+Cerrar()+Guardar()+Deshacer()

CrearDocumento()+NuevoDocumento()+AbrirDocumento()

docs.push_back(doc)doc->Abrir()

MiDocumentoMiAplicacion

C D t ()return new MiDocumento

+CrearDocumento()

39

Page 40: Patrones Libre

Factory MethodFactory Method

A li bilid d U ó d” Aplicabilid ad. Usar este patrón 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 seauxiliares, 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

Page 41: Patrones Libre

Factory Method

” P ti i t

Factory Method

” Participantes.» Product (Documento). Define la interfaz de los objetos que crea

el factory method.y» ConcreteProduct (MiDocumento). Implementa la interfaz del

producto.» Creator (Aplicacion) Declara el factory method Puede también» Creator (Aplicacion). Declara el factory method. Puede también

dar una implementación por defecto del factory method, quedevuelve un objeto de una clase por defecto.

» ConcreteCreator (MiAplicacion) Sobreescribe el factory» ConcreteCreator (MiAplicacion). Sobreescribe el factorymethod para devolver una instancia de ConcreteProduct.

” Colaboraciones.» El creator se apoya en sus subclases para definir el método de

fabricación de manera que éste devuelva una instancia delConcreteProduct adecuado.

41

Page 42: Patrones Libre

Factory Method

” Consecuencias

Factory Method

” Consecuencias .»Los métodos de fabricación eliminan la necesidad de

ligar clases específicas de la aplicación a nuestrog p pcódigo.

»El código sólo trata con la interfaz Product puede»El código sólo trata con la interfaz Product, puedefuncionar con cualquier clase ConcreteProductdefinida por el usuario.

»Proporciona enganches para las subclases. Crearobjetos con un método de fabricación es más flexibleobjetos con un método de fabricación es más flexibleque hacerlos directamente.

»El f t th d h k th d l42

»El factory method es un hook method para que lassubclases den una versión extendida del código.

Page 43: Patrones Libre

Factory MethodFactory Method

”Consecuencias.

Figure ManipulatorFigure Manipulator

+DownClick()+Drag()

…+CreateManipulator() g()

+UpClick()p ()

LineManipulator

+DownClick()+Drag()

TextManipulator

+DownClick()+Drag()

LineFigure

…+CreateManipulator()

TextFigure

…+CreateManipulator() +Drag()

+UpClick()+Drag()+UpClick()

+CreateManipulator() +CreateManipulator()

43

Page 44: Patrones Libre

Factory Method

I l t i ó

Factory Method

” Implementación.»Dos variantes principales:

” Cuando la clase Creator es abstracta y noproporciona implementación para el método defabricación que declarafabricación que declara.

”Cuando la clase Creator es concreta y proporcionauna implementación predeterminada para el métodode fabricación.

»Métodos de fabricación parametrizados:Q l f t th d i ti d”Que los factory methods creen varios tipos deproducto. El método recibe un parámetro queidentifica el tipo de objeto a crear.

44

p j

Page 45: Patrones Libre

Factory MethodFactory Method

” Implementación.class Creator {{public:

Product* GetProduct();protected:

virtual Product* CreateProduct(); // factory methodprivate:

Product* _product;};

Product* Creator::GetProduct () {if ( d t 0) {if (_product == 0) {

_product = CreateProduct();}ret rn prod ct

45

return _product;}

Page 46: Patrones Libre

Factory MethodFactory Method

” Implementación . Se pueden usar plantillas para evitar la herencia (múltiples subclases de Creator).

class Creator {public:

virtual Product* CreateProduct() = 0; // El cliente proporciona sólo 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;

}

Page 47: Patrones Libre

Factory MethodFactory MethodEjemplo

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

}

Page 48: Patrones Libre

Factory MethodFactory MethodEjemplo

class BombedMazeGame : public MazeGame {public:

BombedMazeGame();virtual Wall* MakeWall() constvirtual Wall MakeWall() const{ return new BombedWall; }virtual Room* MakeRoom(int n) const{ return new RoomWithABomb(n); }

};

class EnchantedMazeGame : public MazeGame {blipublic:

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;};

Page 49: Patrones Libre

IndiceIndice

” I t d ió” Introducción.” Patrones de Creación.

P t E t t l”Patrones Estruc tura les.»Compos ite.Co pos te»Facade.»Pro»Proxy.»Adapter.

” Patrones de Comportamiento.” Conclusiones.

494949” Bibliografía.

Page 50: Patrones Libre

Patrones EstructuralesPatrones Estructurales

E t bl ó l bj t” Establecen cómo se componen clases y objetospara formar estructuras mayores queimplementan nueva funcionalidadimplementan nueva funcionalidad.

” Los patrones de clase usan la herencia paracomponer interfaces o implementaciones (ej :componer interfaces o implementaciones (ej.:Adapter).

” Los patrones de objeto describen maneras de” Los patrones de objeto, describen maneras decomponer objetos para implementar nuevafuncionalidadfuncionalidad.» Flexibilidad, ya que se puede cambiar la configuración

en tiempo de ejecución.

50

Page 51: Patrones Libre

CompositeComposite” Propósito.

» componer objetos en estructuras arborescentes pararepresentar jerarquías parte-conjunto.

” M ti ió” Motivac ión.»Aplicaciones gráficas. Manipulación de grupos de figuras de

manera uniformemanera uniforme.

Grafico

dibuja ()graficos*

dibuja ()

Dibujo

dibuja ()añade (Grafico g)

Linea

dibuja ()

Rectangulo

dibuja ()

Texto

dibuja () para todo g en graficosg.dibuja ()

51

elimina (Grafico g)obtenHijo (int) añadir g a la lista de

graficos:graficos.addElement (g)

Page 52: Patrones Libre

CompositeComposite

” Una instancia en tiempo de ejecución :

:Dibujo

” Una instancia en tiempo de ejecución :

:Linea :Texto:Dibujo

graficos graficos graficos

:Linea :Texto:Dibujo

graficosgraficos

:Rectangulo :Texto

Page 53: Patrones Libre

Composite” Aplicabilidad. Usar el patrón cuando:

Composite

» Se quieren representar jerarquías todo/parte de objetos.» Se quiere que los clientes ignoren la diferencia entre composiciones de

objetos y objetos individuales. Los clientes tratarán todos los objetos en j y j jla 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()

Page 54: Patrones Libre

CompositeComposite” Partici pantes.p

» Component (Grafico).” Declara la interfaz de los objetos de la composición.” Implementa el comportamiento por defecto de la interfaz común ap 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 apropiadoen la estructura recursiva y la implementa, si es apropiado.» Leaf (Linea, Rectangulo, …).

” Representa objetos hoja en la composición. Una hoja no tiene hijos.” Define el comportamiento de los objetos primitivos en la composición” Define el comportamiento de los objetos primitivos en la composición.

» Composite (Dibujo)” Define el comportamiento de los objetos con hijos en la composición.” Almacena componentes hijo” Almacena componentes hijo.” Implementa operaciones relacionadas con los hijos de la interfaz de

Component.» Client

54

» Client .” Manipula objetos en la composición a través de la interfaz de

Component.

Page 55: Patrones Libre

CompositeComposite

” 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 petición se cursa directamente.» Si el objeto es un Composite, entonces normalmente redirige las

peticiones a sus objetos hijo, quizá realizando operacionesadicionales antes y/o después de la redirección.

” Consecuencias. El patron composite:» Define jerarquías de objetos primitivos y compuestos Cuando» Define jerarquías de objetos primitivos y compuestos. Cuando

un código cliente espera un objeto simple, se puede reemplazarpor uno compuesto.

» Simplifica el cliente Se pueden tratar objetos simples y» Simplifica el cliente. Se pueden tratar objetos simples ycompuestos de manera uniforme.

» Facilita añadir nuevos tipos de componente.

55

» Puede hacer el diseño demasiado general. Complicado restringirlos tipos de componente de un composite.

Page 56: Patrones Libre

CompositeComposite

” I l t i ó Al d i i” Implementación. Algunas decisiones:» Referencias explícitas a los padres. En la clase component.» Compartir componentes. Útil para ahorrar memoria, pero la» Compartir componentes. Útil para ahorrar memoria, pero la

gestión de un componente que tiene más de un padre es difícil.»Maximizar la interfaz del componente. » Declaración de las operaciones de gestión de hijos Equilibrio» Declaración de las operaciones de gestión de hijos. Equilibrio

entre seguridad y transparencia:” Declararla en la raíz da transparencia. Es menos seguro porque el

cliente puede tratar de hacer cosas sin sentido sobre objetos hojacliente 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.» ¿Quién debe borrar los componentes?» ¿Cuál es la mejor estructura de datos para almacenar los

?56

componentes?.

Page 57: Patrones Libre

CompositeCompositeEjemplo

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 void Add(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

Page 58: Patrones Libre

Composite

class FloppyDisk : public Equipment {public:

Ejemplo

pFloppyDisk(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;};

Page 59: Patrones Libre

CompositeCompositeEjemplo

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

};

Page 60: Patrones Libre

CompositeCompositeEjemplo

using namespace std;

void main(){

Cabinet* cabinet = new Cabinet("PC Cabinet");Chassis* chassis = new Chassis("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

Page 61: Patrones Libre

FacadeFacade” Propósito .

» Proporciona una interfaz unificada para un conjunto de interfaces de unp p jsubsistema.

» Define una interfaz de alto nivel que hace que el subsistema sea más fácilde usar.

” Motivación.» Estructurar un sistema en subsistemas ayuda a reducir su complejidad.» Un objetivo típico de diseño es minimizar la comunicación y dependencias» Un objetivo típico de diseño es minimizar la comunicación y dependencias

entre subsistemas.» Un modo de conseguir esto es introducir un objeto fachada que

proporcione una interfaz única y simplificada a los servicios más generalesdel subsistema.

61

Page 62: Patrones Libre

FacadeFacade

” Motivación.

62

Page 63: Patrones Libre

FacadeFacade” Aplicabilidad. Usar el patrón cuando:

» Queramos proporcionar una interfaz simple a un subsistema complejo.Sólo los clientes que necesitan más personalización necesitarán ir másallá de la fachada.

» Haya muchas dependencias entre los clientes y las clases queimplementan una abstracción. La fachada desacopla el subsistema desus 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 elpunto de entrada a cada subsistema.

” E t t” Estruc tura.

63

Page 64: Patrones Libre

FacadeFacade

” Participantes” Participantes .» Facade (Compiler).

” Sabe qué clases del subsistema son las responsables ante unapeticiónpetición.

” Delega las peticiones de los clientes en los objetos apropiados delsubsistema.

» Clases del Subsistema (Scanner Parser ProgramNodeBuilder» Clases del Subsistema (Scanner, Parser, ProgramNodeBuilder,CodeGenerator).” Implementan la funcionalidad del subsistema.” Realizan las 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 reenvía 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.

Page 65: Patrones Libre

FacadeFacade

” C i” Consecuenc ias.»Oculta a los clientes los componentes del sistema, haciendo

el sistema más fácil de usar.»Promueve acoplamiento débil entre el subsistema y sus

clientes.” Elimina dependencias y puede reducir el tiempo de” Elimina dependencias y puede reducir el tiempo de

compilación.»No impide que las aplicaciones usen las clases del

subsistema en caso necesariosubsistema en caso necesario.

” Implementación. Factores a tener en cuenta:»Reducción del acoplamiento cliente-subsistema. Clase»Reducción del acoplamiento cliente subsistema. Clase

facade abstracta, con clases concretas para las diferentesimplementaciones de un subsistema.

»Clases del subsistema públicas o privadas Uso de espacios65

»Clases del subsistema públicas o privadas. Uso de espaciosde nombres en C++.

Page 66: Patrones Libre

FacadeFacadeEjemplo: Una fachada para un sistema de compilación

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

Page 67: Patrones Libre

Facade

class ProgramNodeBuilder {

FacadeEjemplo: Una fachada para un sistema de compilación

g {public:

ProgramNodeBuilder();virtual ProgramNode* NewVariable ( const char* variableName ) const;virtual ProgramNode* NewAssignment ( ProgramNode* variablevirtual 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

Page 68: Patrones Libre

FacadeEj l U f h d i t d il ióclass ProgramNode {public:

// program node manipulation

Ejemplo: Una fachada para un s istema de comp ilación

// program node manipulationvirtual void GetSourcePosition(int& line, int& index);// ...// child manipulationvirtual void Add(ProgramNode*);virtual void Remove(ProgramNode*);// ...virtual void Traverse(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;};

Page 69: Patrones Libre

Facade

void ExpressionNode::Traverse (CodeGenerator& cg) {Vi it(thi )

FacadeEjemplo: Una fachada para un sistema de compilación

cg.Visit(this);ListIterator i(_children);for (i.First(); !i.IsDone(); i.Next()) {

i.CurrentItem()->Traverse(cg);() ( g);}

}class Compiler { // Clase Facade

blipublic:Compiler();virtual void Compile(istream&, BytecodeStream&);

};};

void Compiler::Compile ( istream& input, BytecodeStream& output ) {Scanner scanner(input);P N d B ild b ildProgramNodeBuilder builder;Parser parser;parser.Parse(scanner, builder);RISCCodeGenerator generator(output);

69

g ( p );ProgramNode* parseTree = builder.GetRootNode();parseTree->Traverse(generator);

}

Page 70: Patrones Libre

ProxyProxy

” Propósito” Propósito .»Proporcionar un representante o substituto de otro objeto

para controlar el acceso a este.

” También conocido como.»Surrogate (substituto).

” M ti ió” Motivac ión.»Retrasar el coste de creación e inicialización de un objeto

hasta que sea realmente necesario.q»Ej.: al abrir un documento, no abrir las imágenes que no sean

visibles.

aTextDocument:

image

anImageProxy:

fileName

anImage:

data

70

en memoria en disco

Page 71: Patrones Libre

ProxyProxy

”Motivación.

71

Page 72: Patrones Libre

ProxyProxy

” Aplicabilidad” Aplicabilidad .»Cuando hay necesidad de una referencia a un objeto más

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 P )ImageProxy).»Proxy de Protección: 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 número de referencias.”Cargar un objeto persistente en memoria.”Bloquear el objeto cuando se accede a él (no modificación

concurrente)72

concurrente).”…

Page 73: Patrones Libre

ProxyProxy” Estructura .Estructura .

73

Page 74: Patrones Libre

ProxyProxy” 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 información adicional sobre el sujeto, para

retardar el acceso al mismo.• Proxy de protección: comprueba que el llamador tiene permiso para

realizar la peticiónrealizar la petición.» Subject.

” Define una interfaz común para el RealSubject y el Proxy, de tal manera que el Proxy se puede usan en vez del RealSubjectmanera que el Proxy se puede usan en vez del RealSubject.

» RealSubject.” Define el objeto real que el proxy representa.

” Colaboraciones74

” Colaboraciones .» El proxy redirige peticiones al sujeto real cuando sea necesario,

dependiendo del tipo de proxy.

Page 75: Patrones Libre

ProxyProxy

” Consecuencias” Consecuencias .» Introduce un nivel de indirección 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 demandabajo demanda.” Tanto los proxies de protección, como las referencias inteligentes

permiten realizar tareas de mantenimiento adicionales cuando se accede a un objetoaccede a un objeto.

» Otra optimización: 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, sólo cuando se hace

una operación que modifica el objeto se copia realmente (ej : clase

75

una operación que modifica el objeto, se copia realmente (ej.: clase String del ejemplo de operadores C++).

Page 76: Patrones Libre

Proxyclass Image;extern Image* LoadAnImageFile(const char*);Proxy

” Implementación

// external functionclass ImagePtr {public:

ImagePtr(const char* imageFile);” Implementación .» Se pueden explotar las

siguientes características del l j

ImagePtr(const char imageFile);virtual ~ImagePtr();virtual Image* operator->();virtual Image& operator*();

los lenguajes:” Sobrecargar el operador de

acceso a miembros -> enC++

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;}

Page 77: Patrones Libre

ProxyProxyImage* 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é operación se llama: entonces hay que definir dichar operación en el proxy y redirigir la llamadallamada.

” 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

Page 78: Patrones Libre

ProxyProxyEjemplo: 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:pGraphic();

};

class Image : public Graphic {public:

Image(const char* file); // loads image from a filevirtual ~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:// ...};

Page 79: Patrones Libre

ProxyProxyEjemplo: Un Proxy Virtual

class ImageProxy : public Graphic { // la clase proxyclass ImageProxy : public Graphic { // la clase proxypublic:

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 tprivate:Image* _image;Point _extent;char* fileName;c a _ e a e;

};

79

Page 80: Patrones Libre

ProxyProxyEjemplo: 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

}

Page 81: Patrones Libre

ProxyProxyEjemplo: Un Proxy Virtual

class TextDocument {public:

TextDocument();void Insert(Graphic*);void Insert(Graphic*);// ...

};

TextDocument* text = new TextDocument;// ...text->Insert(new ImageProxy("anImageFileName"));

81

Page 82: Patrones Libre

Ejercicio (Junio de 208)” S l li ió d did i t t t i” Sea la aplicación de pedidos vista en temas anteriores:

Page 83: Patrones Libre

EjercicioEjercicio

” En el contexto de la aplicación anterior, supónque sólo se puede acceder al disponible de unacuenta de pago si se ha introducido una clave.Utilizando patrones de diseño, implementa enC++ un Proxy de Protección que asegure que seaccede al disponible de la cuenta sólo si la clavees correcta (supón que la clave se pide por laconsola). La clave se almacena en el proxy, yéste recuerda si ya se ha introducidocorrectamente o no.

Page 84: Patrones Libre

Solución (1)#include "stdafx.h"#include <iostream>#include <string>using std::cout;using std::cout;using std::string;using std::cin;class Cuenta {{public:

virtual int obtenerDisponible () = 0;};class CuentaReal : public Cuentaclass CuentaReal : public Cuenta{private:

int disponible;public:public:

CuentaReal (int d ) : disponible (d) {}int obtenerDisponible() {return disponible; }

};class ProxyCuenta: public Cuentaclass ProxyCuenta: public Cuenta{private:

CuentaReal * cuenta;string clave;string clave;bool correcta;bool intro;

public:ProxyCuenta ( string psswd CuentaReal & c ) :ProxyCuenta ( string psswd, CuentaReal & c ) :

clave(psswd), cuenta(&c), intro(false), correcta(false) {}int obtenerDisponible();

};

Page 85: Patrones Libre

Solución (2)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();

}

Page 86: Patrones Libre

AdapterAdapter” Propósito .

» 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 podrían por

tener interfaces incompatibles.” También conocido como .También conocido como .

» Wrapper (envoltorio).” Motivación.

» A veces una clase de una biblioteca que ha sido diseñada para reutilizarse» A veces una clase de una biblioteca que ha sido diseñada para reutilizarse, no puede hacerlo porque su interfaz no coincide con la interfaz específica de dominio que requiere la aplicación.

» Ej : un editor de dibujo Objetos gráficos con una clase base abstracta» Ej.: un editor de dibujo. Objetos gráficos, con una clase base abstracta Shape.” Queremos reutilizar una clase existente TextView para implementar TextShape

(quizá no tengamos el código fuente de TextView).” Solución: 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 implementación de

86

• Adaptador de clase: Heredando el interfaz de Shape y la implementación de TextView.

• Adaptador de objeto: Componiendo un objeto TextView dentro de un TextShape, e implementando TextShape en términos de la interfaz de TextView.

Page 87: Patrones Libre

AdapterAdapter

”Motivación.» Adaptador de objeto.p j

87

Page 88: Patrones Libre

AdapterAdapter

”Estructura.»Adaptador de clase.p

88

Page 89: Patrones Libre

AdapterAdapter

”Estructura.»Adaptador de objeto.p j

89

Page 90: Patrones Libre

IndiceIndice” Introducción.” Patrones de Creación.” Patrones Estructurales.

”Patrones de Comportamiento”Patrones de Comportamiento .»Iterator.»Observer.»Template Method.»State.»Strate gy.gy»Command.»Chain of Responsibility

909090

»Chain of Responsibility .” Conclusiones.” Bibliografía.

Page 91: Patrones Libre

Patrones de ComportamientoPatrones de Comportamiento

”Tratan sobre algoritmos y la asignación de responsabilidades entre objetos.p j

”Describen no sólo patrones de clases y objetos sino patrones de comunicaciónobjetos, sino patrones de comunicación entre ellos.

”Caracterizan un flujo de control complejo, difícil de seguir en tiempo de ejecución.difícil de seguir en tiempo de ejecución.

”Permiten que el diseñador se concentre ól ó i t t bj tsólo en cómo interconectar objetos.

Page 92: Patrones Libre

IteratorIterator

” Propósito” Propósito .» Proporciona un medio de acceder a los elementos de un

contenedor secuencialmente sin exponer su representación internainterna.

” También Conocido Como .» Cursor.

” Motivación .» Un contenedor (p.ej.: una lista) debe proporcionar un medio de

navegar sus datos secuencialmente sin exponer su g prepresentación interna.

» Se debe poder atravesar la lista de varias maneras, dependiendo de lo que se quiera hacer.

» Probablemente no interesa añadir a la lista operaciones para realizar los diferentes recorridos.

» Puede necesitarse hacer más de un recorrido simultáneamente.

92

» Dar la responsabilidad de acceder y recorrer el objeto lista a un objeto Iterator.

Page 93: Patrones Libre

IteratorIterator

” Motivación.

List ListIterator1 *

list

+ Count()+ Append(Element)+ Remove(Element) + First()

+ Next()

- index1 *

+ 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 secuencialmenteelementos de la lista secuencialmente.» Separar el mecanismo de recorrido del objeto lista, nos permite

definir iteradores que implementen distintas estrategias.

93

Page 94: Patrones Libre

IteratorIterator

” Motivación.» El iterador y la lista están acoplados: el cliente sabe que lo que se está recorriendo es una lista.» Es mejor poder cambiar el contenedor sin tener que cambiar el código cliente: iteración

polimórfica.

AbstractList

+CreateIterator()+ Count()

A d(El t)

Iterator+ First()+ Next()

Cli t+ Append(Element)+ Remove(Element)…

Next()+ IsDone()+ CurrentItem()

Client

1 *list

ListSkipList ListIterator SkipListIterator1

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 genérico (en C++: “for_each”, “find_if”,

“count”, etc)

Page 95: Patrones Libre

IteratorIterator” Aplicabilidad. Usar el patrón :

» para acceder al contenido de un contenedor sin exponer su» para acceder al contenido de un contenedor sin exponer su representación interna.

» para permitir varios recorridos sobre contenedores.» para proporcionar una interfaz uniforme para recorres distintos tipos

de contenedores (esto es, permitir la iteración polimórfica).

” Estructura. Iterator

Aggregate

+CreateIterator ()

Iterator

+First ()+Next ()+IsDone ()

Client

IsDone ()+CurrentItem ()

ConcreteAggregate

+CreateIterator () ConcreteIterator

95return new ConcreteIterator (this)

Page 96: Patrones Libre

IteratorIterator

” Participantes” Participantes .» Iterator.

” Define una interfaz para recorrer los elementos y acceder a ellos.» ConcreteIterator.

” Implementa la interfaz Iterator.” Mantiene la posición actual en el recorrido del agregado.

» Aggregate.” Define una interfaz para crear un objeto Iterator.

» ConcreteAggregate.” Implementa una interfaz de creación del Iterator para devolver una

instancia del ConcreteIterator apropiado.

” Colaboraciones .» Un ConcreteIterator sabe cuál es el objeto actual del agregado y

puede calcular el objeto siguiente del recorrido.

96

Page 97: Patrones Libre

IteratorIterator

” Consecuencias” Consecuencias .» Permite variaciones en el recorrido de un agregado.» Los iteradores simplifican la interfaz del contenedor.» Se puede hacer más de un recorrido a la vez sobre un

agregado.” Implementación.” Implementación.

»¿Quién controla la iteración?. ”El cliente controla la iteración: iterador externo .”El iterador controla la iteración: iterador interno”El iterador controla la iteración: iterador interno .

»¿Quién define el algoritmo de recorrido?”El iterador.”El d l it d ól l l t d d l”El agregado, y el iterador sólo almacena el estado de la

iteración. A este tipo de iterador se le llama cursor .»¿Cómo de robusto es el iterador?

” Iterador robusto: Las inserciones y borrados no interfieren en el97

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

Page 98: Patrones Libre

IteratorIterator

” I l t i ó” Implementación.»Operaciones adicionales del iterador.

”Por ejemplo, iteradores ordenados podrían tener una operación”Por ejemplo, iteradores ordenados podrían tener una operación Previous. Otras como SkipTo.

»Usar iteradores polimórficos en C++.” Los iteradores polimórficos han de crearse dinámicamente por un” Los iteradores polimórficos han de crearse dinámicamente por un

método de fabricación.”El cliente además es responsable de borrarlos (propenso a

errores)errores).» Iteradores para Composites.

” Los iteradores externos pueden ser complicados de implementar t t ien estructuras recursivas.

»NullIterators.”Es un iterador degenerado que ayuda a manejar condiciones

98

g q y jlímite.

Page 99: Patrones Libre

Iterator

1 Interfaces de la lista y el iterador

IteratorEjemplo

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();

};

Page 100: Patrones Libre

Iterator

2 Implementaciones de las subclases del iterador

IteratorEjemplo

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

Page 101: Patrones Libre

Iterator

3 U d l i d

IteratorEjemplo

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

Page 102: Patrones Libre

IteratorIteratorEjemplo

4. Evitar a justarse a una im plementación 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 iteración polimórfica, 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 AbstractListyAbstractList<Employee*>* employees;// ...Iterator<Employee*>* iterator = employees->CreateIterator();P i tE l (*it t )

102

PrintEmployees(*iterator);delete iterator;

Page 103: Patrones Libre

IteratorIteratorEjemplo

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

_};

Page 104: Patrones Libre

Iterator

6. Un iterador interno.

IteratorEjemplo

» El iterador controla la iteración, y aplica una operación a cada elemento.» La operación se puede configurar:

” Pasando un puntero a una función o a un objeto función” Pasando un puntero a una función, o a un objeto función.” Mediante subclasificación.

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;

}return result;

ListIterator<Item> _iterator;};

return result;}

104

Page 105: Patrones Libre

Iterator

6 U i d i

IteratorEjemplo

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;

}

Page 106: Patrones Libre

Iterator

6 U it d i t

IteratorEjemplo

List<Employee*>* employees;

6. Un iterador interno» Imprimir los n primeros empleados de una lista.

List Employee employees;// ...PrintNEmployees pa(employees, 10);pa.Traverse();

» Comparación 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

Page 107: Patrones Libre

Iterator

6 U i d i

IteratorEjemplo

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

Page 108: Patrones Libre

ObserverObserver

” P ó it” Prop ósito.»Define una dependencia de uno-a-muchos entre objetos, de

forma que cuando un objeto cambie de estado se notifique y q j q yactualicen automáticamente todos los objetos que dependen de él.

” También conocido como” También conocido como .»Dependents, Publish-Subscribe

” Motivación .»Mantener consistencia entre objetos relacionados.»No queremos obtener dicha consistencia aumentando el

acoplamiento entre clasesacoplamiento entre clases.»Ej.: separación de la presentación en GUI de los datos de

aplicación subyacente.

108

Page 109: Patrones Libre

ObserverObserver

” Motivación.

40

A

C

D

10

20

30

40

A B C D

X 60 20 15 5

Y 40 25 15 20B 0

A B C D

Y 40 25 15 20

Z 10 10 20 60

ModeloA: 40%B: 25%C 15%

109

C: 15%D: 20%

Page 110: Patrones Libre

ObserverObserver” Aplicabilidad .

» Cuando una abstracción tiene dos aspectos y uno depende del otro.» Cuando un cambio en un objeto requiere cambiar otros, y no sabemos

cuántos hay que cambiar.y q» Cuando un objeto debería ser capaz de notificar a otros sin hacer

suposiciones sobre quiénes son dichos objetos (esto es, no queremos que los objetos estén fuertemente acoplados)que los objetos estén fuertemente acoplados).

” Estructura.Subject Observer

observers

1 *0 1

+Attach (Observer)+Detach (Observer)+Notify ()

+Update()

forall o in observerso.Update()

1..*0..1

o.Update()

ConcreteSubject

ConcreteObserver

- observerStatesubject

0..1

110+GetState ()+SetState ()

- subjectState +Update ()subject

return subjectState observerState=subject->GetState()

Page 111: Patrones Libre

ObserverObserver” Participantes .

» S bj t» Subject.” Conoce a sus observadores, que pueden ser un número arbitrario.” Proporciona un interfaz para añadir y quitar objetos Observer.

» Ob» Observer.” Define un interfaz de actualización para los objetos que deben ser

notificados sobre cambios en un sujeto.» ConcreteSubject» ConcreteSubject.

” Almacena estado de interés 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 actualización del Observer para mantener su” Implementa el interfaz de actualización del Observer para mantener su

estado consistente con el del sujeto.

111

Page 112: Patrones Libre

ObserverObserver” 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

» Después de ser notificado del cambio, un ConcreteObserver puede pedir al subject más información.

:ConcreteSubject barDiagram:ConcreteObserver

sectorDiagram:ConcreteObserver

SetState()Notify()

Update()

GetState()GetState()

Update()GetState()

112

Page 113: Patrones Libre

ObserverObserver

” 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 añadir observadores sin modificar el sujeto u otros

observadoresobservadores.» Acoplamiento abstracto entre sujeto y observador. El sujeto no

conoce la clase concreta de ningún observador (el acoplamientoes mínimo)es mínimo).

» Capacidad de comunicación mediante difusión. La notificacióndel sujeto se envía automáticamente a todos los observadoressuscritos. Se pueden añadir y quitar observadores en cualquierp y q qmomento.

» Actualizaciones inesperadas. Una operación aparentementeinofensiva sobre el sujeto puede desencadenar una cascada de

bi l b d113

cambios en los observadores.

Page 114: Patrones Libre

ObserverObserver

” Implementación” Implementación .» Correspondencia entre sujetos y observadores.

” Que el sujeto guarde referencias a los observadores a los que debe notificarnotificar.

» Observar más de un sujeto.” Ej.: una hoja de cálculo puede observar más de un origen de datos.” Extender la interfaz de actualización para que el observador sepa” Extender la interfaz de actualización para que el observador sepa

qué sujeto se ha actualizado (quizá simplemente el sujeto se pase a sí mismo como parámetro del update()).

» ¿Quién dispara la actualización?¿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 sólo después de varios

cambios.• Inconveniente: los clientes tienen la responsabilidad añadida de llamar

114

Inconveniente: los clientes tienen la responsabilidad añadida de llamar a Notify().

Page 115: Patrones Libre

ObserverObserver

” Implementación .»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 notificación:” 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

}

Page 116: Patrones Libre

ObserverObserver

” Implementación” Implementación .»Evitar protocolos específicos del obervador: los modelos

push y pull.” Las implementaciones de observer suelen hacer que el sujeto

envie información adicional como parámetro de Update().”Dos extremos:

• Modelo Push: el sujeto envía información detalla del cambio quieran• Modelo Push: el sujeto envía información detalla del cambio, quieran los observadores o no.

Inconveniente: observadores menos reutilizables.• Modelo Pull: el sujeto no envía nada, y los observadores piden

d é l d t ll lí it tdespués los detalles explícitamente.Inconveniente: puede ser poco eficiente.

»Especificar las modificaciones de interés explícitamente:”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

Page 117: Patrones Libre

ObserverObserver” Implementación .

» Encapsular la semántica de las operaciones complejas» Encapsular la semántica de las operaciones complejas.” Si la relación de dependencia entre sujetos y observadores es compleja, puede ser

necesario un objeto intermedio para la gestión 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 sólo después del cambio en el último sujeto.

Subject

+Attach (Observer o)

Observer

+Update(Subject)

subjects

1..*0..*ChangeManager

chman

1Subject-Observer mapping

observers

+Attach (Observer o)+Detach (Observer)+Notify ()

+Update(Subject)+Register (Subject,Observer)+Unregister (Subject,Observer)+Notify ()

chman->Notify()

Marcar todos los observersa actualizar.Actualizar los observerschman >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)

Page 118: Patrones Libre

ObserverObserverEjemplo

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 múltiples subjectsprotected:

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

}

Page 119: Patrones Libre

ObserverObserverEjemplo

class ClockTimer : public Subject { class DigitalClock: public Widget, publicclass ClockTimer : public Subject {// Concrete subjectpublic:

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();void Tick();

virtual ~DigitalClock();virtual void Update(Subject*);// overrides Observer operationvirtual 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);

}

Page 120: Patrones Libre

ObserverObserverEjemplo

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);

Page 121: Patrones Libre

Observer

” Sistemas de eventos en Java (observer listener)

ObserverUsos Conocidos

” Sistemas de eventos en Java (observer=listener)»AWT/Swing» Javabeans

” 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 (J2EE)»Model=EJB»View=JSP»Controller=servlet»Controller servlet

121

Page 122: Patrones Libre

Template MethodTemplate Method” Propósito .p

» Definir el esqueleto de un algoritmo, delegando en las subclasesalguno de sus pasos.

» Permite que las subclases cambien pasos de un algoritmo sin cambiar» Permite que las subclases cambien pasos de un algoritmo sin cambiarsu estructura.

” Motivación .» Ej.: MFCs, abrir un fichero.

Document Applicationdocs1 *

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 documentreturn;

}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();}

}

Page 123: Patrones Libre

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 variarque puede variar.

»Cuando el comportamiento repetido de varias subclases debería factorizarse y localizarse en una clase común, para evitar código duplicado.

»Para controlar las extensiones de las subclases.

” E t t” Estruc tura. ClaseAbstracta

+TemplateMethod()+PrimitiveOperation1() …+PrimitiveOperation2()+…

…PrimitiveOperation1()…PrimitiveOperation2()

123

ConcreteClass

+PrimitiveOperation1()+PrimitiveOperation2()

Page 124: Patrones Libre

StateState” Propósito .

» 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.” También conocido como.

» Objets for state (estados como objetos).” Motivación .

» TCPConnection para representar una conexión de red.p p» Puede estar en distintos estados: establecida, escuchando y cerrada.» El efecto de cada petición sobre cada objeto depende del estado en el que está.

124

Page 125: Patrones Libre

StateState

”Estructura.

125

Page 126: Patrones Libre

StrategyStrategy” Propósito.

» Define una familia de algoritmos, encapsula cada uno de ellos, y los hace intercambiables.

» Permite que un algoritmo varíe independientemente de los clientes que los usan.

” También conocido como.» Policy (política).

” Motivación” Motivación .» Ej.: Algoritmos para dividir en líneas un flujo de texto.» Clases que encapsulen los distintos algoritmos de división. Un algoritmo así

encapsulado se denomina estrategiaencapsulado se denomina estrategia .

126

Page 127: Patrones Libre

StrategyStrategy

”Estructura .

127

Page 128: Patrones Libre

CommandCommand” Propósito.

» 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 peticionespeticiones.

” También conocido como.» Action, Transaction.

M ti ió” Motivac ión.» Framework gráfico tipo MFC. Peticiones de los distintos widgets

encapsuladas como objetos.

128

Page 129: Patrones Libre

CommandCommand

”M ti ió”Motivac ión.

129

Page 130: Patrones Libre

CommandCommand

” E t t” Estruc tura.

130

Page 131: Patrones Libre

Chain of ResposibilityChain of Resposibility” Propósito.

» Evita acoplar el emisor de una petición a su receptor, dando a más de un objeto la posibilidad de responder a la petición.

» Encadena los objetos receptores y pasa la petición a través de la» Encadena los objetos receptores y pasa la petición a través de la cadena hasta que es procesada por algún objeto.

” Motivación.» Ej.: ayuda sensible al contexto en una GUI.» Si no existe ayuda para una parte de la interfaz, se muestra ayuda

para una parte más general.p p g

131

Page 132: Patrones Libre

Chain of ResposibilityChain of Resposibility

”Motivación.

132

Page 133: Patrones Libre

Chain of ResposibilityChain of Resposibility

”Estructura.

133

Page 134: Patrones Libre

IndiceIndice

” I t d ió” Introducción.” Patrones de Creación.” Patrones Estructurales” Patrones Estructurales.” Patrones de Comportamiento.

”Conclusiones”Conclusiones .” Bibliografía.

134134134

Page 135: Patrones Libre

ConclusionesConclusiones

”Los patrones de diseño capturan el conocimiento que”Los patrones de diseño capturan el conocimiento quetienen los expertos a la hora de diseñar.

”Los patrones ayudan a generar software “maleable”(software que soporta y facilita el cambio, la reutilizacióny la mejora)y la mejora).

”Los patrones de diseño son guías, no reglas rigurosas.

”Cada patrón describe la solución a problemas que serepiten una y orta vez en nuestro entorno de forma querepiten una y orta vez en nuestro entorno, de forma quese puede usar esa solución todas las veces que hagafalta.

135

Page 136: Patrones Libre

IndiceIndice

” I t d ió” Introducción.” Patrones de Creación.” Patrones Estructurales” Patrones Estructurales.” Patrones de Comportamiento.” Conclusiones” Conclusiones.

”Bibliografía.

136136136

Page 137: Patrones Libre

BibliografíaBibliografía

“D i tt l t f bl bj t” “Design patterns, elements of reusable object-oriented software”. Gamma, Helm, Jonhnson, Vlissides Addison Wesley 1995 (traducido alVlissides. Addison Wesley, 1995 (traducido al español en 2003).

” “Applying UML and Patterns. An introduction to Object Oriented Analysis and Design andObject-Oriented Analysis and Design and Iterative Development. 3rd Edition.” Craig Larman Prentice Hall 2005Larman. Prentice Hall.2005.

” http://hillside net/137137137

” http://hillside.net/