Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Tecnicas Avanzadas de Diseno de Software PDF
Tecnicas Avanzadas de Diseno de Software PDF
Diseño de Software
Diseño de
Componentes
Dra. Marcela
Capobianco
1
Diseño orientado a objetos
Recordemos
Los patrones de diseño son básicamente
descripciones de objetos que se
comunican y clases que son
personalizadas para resolver un problema
de diseño general en un contexto
particular [GoF]
Patrones de diseño GoF
PROPÓSITO
*
Patrones GoF - creacionales
*
AbstractFactory AbstractProductA
* *
CreateProductA() *
CreateProductB() *
ProductA2 ProductA1
ConcretFactory1 ConcretFactory2
CreateProductA() + CreateProductA() +
CreateProductB() + CreateProductB() +
AbstractProductB
*
ProductB2 ProductB1
Participantes
StandardMazeBuilder::StandardMazeBuilder () { _currentMaze = 0
void StandardMazeBuilder::BuildMaze () { _currentMaze =
new Maze; }
Maze* StandardMazeBuilder::GetMaze () { return
_currentMaze; }
Patrón Builder - laberintos
void StandardMazeBuilder::BuildRoom (int
n) {
if (!_currentMaze->RoomNo(n)) {
Room* room = new Room(n);
_currentMaze->AddRoom(room); Maze* maze;
room->SetSide(North, new Wall); MazeGame game;
room->SetSide(South, new Wall); StandardMazeBuilder bld
room->SetSide(East, new Wall); …
room->SetSide(West, new Wall); game.CreateMaze(bldr);
} maze = bldr.GetMaze();
}
void StandardMazeBuilder::BuildDoor (int n1,
int n2) {
Room* r1 = _currentMaze->RoomNo(n1);
Room* r2 = _currentMaze->RoomNo(n2);
Door* d = new Door(r1, r2);
r1->SetSide(CommonWall(r1,r2), d);
r2->SetSide(CommonWall(r2,r1), d);
}
Patrón Factory Method
// factory methods:
virtual Maze* MakeMaze() const
{ return new Maze; }
virtual Room* MakeRoom(int n) const
{ return new Room(n); }
virtual Wall* MakeWall() const
{ return new Wall; }
virtual Door* MakeDoor(Room* r1, Room* r2) const
{ return new Door(r1, r2); }
};
Podemos implementar CreateMaze en función de estos factory
methods. Diferentes juegos pueden heredar de MazeGame y
redefinir partes específicas del laberinto.
Patrón Prototype
private:
Maze* _prototypeMaze;
Room* _prototypeRoom;
Wall* _prototypeWall;
Door* _prototypeDoor;
};
El constructor inicializa los prototipos con los
parámetros.
Patrón Prototype
Las funciones miembro para crear habitaciones, puertas
paredes simplemente solicitan clones a los prototipos.
•Participantes:
Singleton
• Define una operación Instance que permite a los
clientes acceder su instancia única.
• Es una operación de la clase (static). Es
responsable por crear su propia instancia única.
Patrón Singleton
Si necesitamos que exista una única instancia de
la clase MazeFactory que produce el laberinto,
debemos contemplar la siguiente estructura:
class MazeFactory {
public:
static MazeFactory*
Instance();
protected:
MazeFactory();
private:
static MazeFactory* _instance;
};
Bibliografía
Recordemos
Los patrones de diseño son básicamente
descripciones de objetos que se
comunican y clases que son
personalizadas para resolver un problema
de diseño general en un contexto
particular [GoF]
Patrones de diseño GoF
PROPÓSITO
•Participantes:
• Target: define la interfase específica del
dominio que usa el cliente
• Client: Colabora con los objetos que se ajustan
a la interfaz de target
• Adaptee: Define una interfaz que se necesita
adaptar
• Adapter: Adapta la interfaz de adaptee a target
class Shape {
public: Interfaz
Shape(); esperada en
virtual void BoundingBox(Point& bttmLft, Point& nuestra
tpRight) const;
virtual Manipulator* CreateManipulator() const; aplicación
};
class TextView {
public: Clase que
TextView(); queremos
void GetOrigin(Coord& x, Coord& y) const; usar, pero la
void GetExtent(Coord& width, Coord& height)
interfaz es
const;
virtual bool IsEmpty() const; incompatible
}; .
class TextShape : public Shape, private TextView {
public: Clase que
TextShape(); adapta
virtual void BoundingBox(Point& bttmLft, Point&
tpRght) const; TextView
virtual bool IsEmpty() const; con la
virtual Manipulator* CreateManipulator() const; interfaz
}; Shape
Patrón Adapter
El object-adapter utiliza composición de objetos en lugar
de herencia múltiple.
class TextShape : public Shape {
public:
TextShape(TextView*);
virtual void BoundingBox(Point& bttmLft, Point&
topRight) const;
virtual bool IsEmpty() const;
virtual Manipulator* CreateManipulator() const;
private:
TextView* _text;
};
Bridge
Patrón Bridge
•Participantes:
• Abstraction: define la interfaz de la abstracción y
mantiene una referencia a un objeto de tipo
Implementor.
• RefinedAbstraction: extiende la interfaz definida
por Abstraction.
• Implementor: define la interfaz para clases de
implementación. No necesariamente debe
corresponder a la interfaz Abstraction.
• ConcreteImplementor: implementa la interfaz
Implementor y define su implementación
concreta.
Leer ejemplo de implementación (abstracción
Window) del libro de Gamma et al.
Patrón Bridge
Leer ejemplo de implementación (abstracción
Window) del libro de Gamma et al.
Decorador Concreto
class BorderDecorator : public Decorator {
public:
BorderDecorator(VisualComponent*, int
borderWidth);
virtual void Draw(); {
private:
void DrawBorder(int); Decorator::Draw
private: ();
int _width;
}; DrawBorder(_wid
th);
}
Patrón Decorator - ejemplo
Supongamos que tenemos esta operación en Window, para
agregar componentes visuales
void Window::SetContents (VisualComponent* contents) {
// ...
}
Creamos un objeto TextView y una ventana en la cual ubicarlo.
Window* window = new Window;
TextView* textView = new TextView;
window->SetContents(textView);
Pero como queremos un TextView con borde y con barra de
desplazamiento (scroll bar), lo decoramos acordemente antes de
ubicarlo en la ventana.
window->SetContents(
new BorderDecorator( new ScrollDecorator(textView), 1)
);
•Participantes:
• Flyweight: declara una interfaz por medio de la
cual los objetos flyweight pueden actuar sobre el
estado extrínseco.
• ConcreteFlyweight: implementa la interfaz
Flyweight y agrega almacenamiento para el
estado intrínseco.
• UnsharedConcreteFlyweight: objeto flyweight no
compartible.
Patrón Flyweight
•Estructura dinámica:
Patrón Proxy
• Participantes:
• Proxy: mantiene una referencia que le permite al
proxy acceder al objeto real.
Provee una interfaz idéntica a Subject de forma tal
que el proxy puede sustituir al objeto real.
Controla el acceso al objeto real.
• Subject: define la interfaz común para RealSubject y
Proxy de forma tal que Proxy pueda ser usada en
cualquier lugar en el que se espere usar RealSubject.
• RealSubject: define el objeto real que el proxy
representa.
class Graphic { Interfaz para los
public: objetos gráficos.
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:
Graphic();
};
class Image : public Graphic { Clase para
public:
Image(const char* file); // carga imagen de
mostrar
archivo archivos de
virtual ~Image(); imágenes.
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);
... };
class ImageProxy : public Graphic { Proxy para las
public: imágenes.
ImageProxy(const char* imageFile);
virtual ~ImageProxy(); Tiene la misma
virtual void Draw(const Point& at); interfaz que
virtual void HandleMouse(Event& Image
event);
virtual const Point& GetExtent();
virtual void Load(istream& from);
virtual void Save(ostream& to);ImageProxy::ImageProxy (const char*
protected: fileName) {
Image* GetImage(); _fileName = strdup(fileName);
private: _extent = Point::Zero;
Image* _image; _image = 0;
Point _extent; }
char* _fileName;
};
Image* ImageProxy::GetImage() {
if (_image == 0) {
_image = new Image(_fileName);
}
return _image;
}
Patrón Proxy
GetExtent del proxy retorna el tamaño almacenado, si
no es posible se lo consulta a la imagen real.
const Point& ImageProxy::GetExtent () {
if (_extent == Point::Zero) {
_extent = GetImage()->GetExtent();
}
return _extent;
}
Recordemos
Los patrones de diseño son básicamente
descripciones de objetos que se
comunican y clases que son
personalizadas para resolver un problema
de diseño general en un contexto
particular [GoF]
Patrones de diseño GoF
PROPÓSITO
• Participantes:
• Handler: define una interfaz para atender
pedidos. Implementa opcionalmente el link
sucesor.
• ConcreteHandler: atiende los pedidos por los
cuales es responsable. Puede acceder a sus
sucesor.
• Client: inicia el pedido a un objeto
ConcreteHandler de la cadena.
•Participantes:
• Strategy: declara una interfaz común a todos los
algoritmos soportados.
• ConcreteStrategy: implementa un algoritmo
utilizando la interfaz Strategy.
• Context: está configurado con un objeto de tipo
ConcreteStrategy. Mantiene una referencia a un
objeto Strategy. Puede definir, si es necesario,
una interfaz para que Strategy acceda a sus
datos.
Algoritmos en términos
abstractos
Es posible que se conozca la estructura general de un
algoritmo, pero que ciertos detalles deban resolverse
en situaciones específicas.
Podemos implementar el algoritmo en función de
ciertas primitivas abstractas, las cuales serán
redefinidas por los herederos correspondientes. Esta
operación se denomina template method.
Las subclases proveen de esta forma el
comportamiento concreto de la operación antes
especificada, implementando los pasos que son
abstractos en el template method.
Patrón Template Method
•Intención: Define el esqueleto de un algoritmo en
una operación, postergando la implementación de
algunos pasos a las subclases. Las subclases
redefinen ciertos pasos del algoritmo sin cambiar su
estructura general.
•Aplicabilidad: Usaremos este patrón cuando:
• Es conveniente implementar la parte invariante
de un algoritmo sólo una vez y dejar que las
subclases implementen el comportamiento
variante.
• El comportamiento común de varias subclases
puede ser factorizado y ubicado en una clase
común para evitar la duplicación de código.
• Para controlar las extensiones por subclases. La
extensión se permite en ciertos puntos de un
algoritmo.
Patrón Template Method
Participantes
AbstractClass: define
operaciones primitivas
abstractas.
ConcreteClass: implementa
las operaciones primitivas
específicas.
Repartiendo tareas..
Supongamos que tenemos una estructura de objetos
medianamente compleja, por ejemplo un árbol, en la
cual debemos realizar una operación que requiere
operar con cada objeto de la estructura.
Repartiendo tareas..
Replicar estas operaciones por cada tipo de nodo
que podemos encontrar puede ser tedioso, y el
resultado global difícil de entender, mantener y
modificar.
En lugar de incluir en cada clase operaciones que
permiten realizar cálculos en cada instancia de esas
clases, podemos encapsular una única operación en
un objeto que será pasado a cada objeto de la
estructura.
Este objeto se denomina visitador (visitor) pues
“visita” todos los objetos, realizando la operación
indicada. Cada objeto visitado acepta esta visita y se
ofrece como participante del cálculo general.
Patrón Visitor
•Intención: Representa una operación a realizarse
sobre los elementos de una estructura. Permite
definir una nueva operación sin cambiar la clases de
elementos sobre los cuales opera.
•Aplicabilidad: Usaremos este patrón cuando:
• Un objeto estructura contiene muchas clases de
objetos con diferentes interfaces y deseamos realizar
operaciones sobre esos objetos.
• Muchas operaciones distintas y no relacionadas
necesitan realizarse sobre objetos en una estructura, y
no deseamos “contaminar” las clases con estas
operaciones.
• Las clases definiendo una estructura de objetos
raramente cambia, pero usualmente deseamos definir
nuevas operaciones sobre la estructura.
Patron Visitor -
Colaboraciones