Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

ISG: Patrón de diseño Composite

Test ISG
by

Fernando González

on 14 May 2011

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of ISG: Patrón de diseño Composite

Patrón
Composite Introducción Tenemos un programa de dibujo
con el que podemos hacer líneas un ejemplo Un programa para resolver funciones otro ejemplo 2x 5x 3x 10x x 2 3 + 7 5 4 - X ) ) ) ( ( ( + Motivación ideas ¡Qué ilusión!
¡Hoy toca ISG! ¿qué necesitamos? un sistema básico de archivos el último
ejemplo queremos poder agrandar,
cambiar de color, girar... a
todo el conjunto a la vez necesitamos funciones para resolver y
para mostrar la solución sin importar si
es simple o compuesto requisitos Elementos simples
Elementos compuestos/contenedores
Agrupar indistintamente Operaciones en común
Manejo con transparencia
Ignorar el tipo de elemento como las operaciones con las líneas o
las funciones para los polinomios Simple Compuesto Simple Simple Compuesto Simple Compuesto Simple Compuesto Estructura Elementos Consecuencias Implementación ¿Cuándo usar el patrón composite? Ejemplo: Dudas Un poco más allá diagrama de secuencia Tenemos dos tipos de elementos diferenciados Creamos clases diferentes queremos manipularlo todo como un solo elemento! Simples y compuestos son tratados diferentes
Comprobaciones en código para saber con qué estamos tratando Participantes: Component:
Declara la interfaz para los objetos de la composición.
Declara una interfaz para acceder y manejar a los componentes hijos. Queremos agrupar simples y/o compuestos Dentro de los compuestos añadimos los simples ¿Y como añadimos compuestos a compuestos?
¿Cuántos niveles podemos agrupar?
El compuesto debe afectar a todos sus elementos! necesitamos que sea transparente! Necesitamos un patrón de diseño Leaf:
Representa objetos hojas dentro del árbol de composición.
Define el comportamiento para los objetos primitivos de la composición. Composite:
Define el comportamiento para los componentes que tienen descendencia.
Almacena componentes hijo.
Implementa las operaciones de Component para la gestion de hijos. client:
Manipula los objetos de la composición a traves de la interfaz del componente. Ventajas: Define jerarquía de clases consistentes en objetos primitvos
y compuestos.
Hace el cliente sencillo.
Facilita el añadir nuevos tipos de componentes. Agregar archivos dentro de carpetas y éstas dentro de carpetas a su vez Eliminar el elemento
Mostrar el contenido Mismas operaciones para todos Desventaja: Puede hacer que el diseño sea demasiado general. Cadena de responsabilidades
Decorator
Flyweight
Iterator Puntos a considerar: Mantener referencias en los descendientes a sus padres puede simplificar el recorrido y manejo de una estructura recursiva.
Las referencias al padre también ayudan a la hora de dar soporte al patrón. Referencias explícitas a superclases: Maximizando la interfaz del Componente: Uno de los objetivos del patrón Composite es hacer posible que el cliente no necesite conocer las clases Hoja o Compuesto que está usando.

Para lograr este objetivo la clase Componente debería definir tantas operaciones comunes para las clases Compuesto y Hoja como sea posible.

Lo normal es que la clase Componente proporcione implementaciones por
defecto para estas oeraciones, y luego las subclases Hoja y Compuesto las redefinan. ¿Debería Componente implementar una lista de Componentes? Se podría caer en la tentación de definir el conjunto de hijos como atributos en la clase
Componente donde se declaran las operaciones de acceso y manejo de los hijos.

Pero poner el puntero hijo en la clase base provoca una penalización de espacio para cada hoja. Ordenación de los descendientes Muchos diseños especifican un orden en los hijos de un Compuesto.

Cuando el orden de los hijos es importante se deben diseñar cuidadosamente los accesos a
los descendientes y las interfaces para manejarlos.

En una aplicación gráfica, por ejemplo, por orden se puede entender la colocación uno encima del otro de los elementos que aparezcan en la pantalla. Declarar las operaciones de manejo de la descendencia: Aunque la clase Compuesto implementa las operaciones añadir y eliminar para el manejo de los hijos, un aspecto a considerar en este patrón es decidir dónde se declaran estas operaciones en la jerarquía de clases.

Una posibilidad es declarar una operación Composite * getComposite() en la clase Componente. El Componente proporciona una operación por defecto que devuelve un puntero a null, que será lo que se obtenga cuando se llame sobre una Hoja, porque no la redefinirán. La clase Compuesto, en cambio, sí lo hará y se devolverá a sí misma mediante el
puntero this (C++).

Véase el siguiente ejemplo para más claridad: Class Composite;

Class Component {
Public:
...
virtual Composite * GetComposite() { return 0; }
};

class Composite : public Component {
// El cliente recibirá en su llamada
// a GetComposite un puntero a objeto Composite
public:
void Add(Component *);
...
virtual Composite * GetComposite() { return this; }
};

class Leaf : public Component {
// El cliente recibirá en su llamada a
// GetComposite un puntero a null, debido a que se usará la
// operación por defecto definida en la clase Component
...
}; class Componente{
protected:
char miNombre[20];
unsigned int miPrecio;

public:
Componente(const char *nombre, unsigned int precio) {
strcpy(miNombre, nombre);
miPrecio = precio;
};
//Por defecto hacemos que Add y Remove fallen.
//De este modo se evita que se puedan añadir
//elementos a un nodo Pieza
virtual int Add(Componente *){ return 1; }
virtual int Remove(Componente *){ return 1; }
virtual unsigned int ObtenerPrecio() = 0;

//Sobrecargamos ObtenerPrecio para averiguar
//El precio concreto de una Pieza dentro del compuesto
virtual unsigned int ObtenerPrecio(const char *nombre) = 0;
virtual void contenido() = 0;
virtual Componente * ObtenerHijo(const char *) = 0;
}; class Compuesto: public Componente {
private:
list <Componente *> miLista;

public:
Compuesto(const char *nombre, unsigned int precio)
:Componente(nombre, precio){};
virtual int Add(Componente *c);
virtual int Remove(Componente *c);
virtual unsigned int ObtenerPrecio();
virtual unsigned int ObtenerPrecio(const char *nombre);
virtual Componente * ObtenerHijo(const char *nombre);
virtual void contenido();
}; class Pieza : public Componente {
public:

Pieza(const char *nombre, unsigned int precio):Componente(nombre, precio) {};
virtual Componente * ObtenerHijo(const char *nombre) {
if(strcmp(miNombre, nombre) == 0)return this;
return 0;
};
virtual unsigned int ObtenerPrecio(const char *nombre) {
if(strcmp(miNombre, nombre) == 0)return miPrecio;
return 0;
};
virtual unsigned int ObtenerPrecio() {
return miPrecio;
};
virtual void contenido() {
cout << " Pieza: " << miNombre << endl;
};
}; int Compuesto::Add(Componente *c) {
miLista.push_front(c);
return 0;
};

int Compuesto::Remove(Componente *c) {
miLista.remove(c);
return 0;
};

unsigned int Compuesto::ObtenerPrecio() {
unsigned int total;
list <Componente *>::iterator i;
total = miPrecio;

for(i = miLista.begin(); i != miLista.end(); i++)
total += (*i)->ObtenerPrecio();

return total;
}

unsigned int Compuesto::ObtenerPrecio(const char *nombre) {
list <Componente *>::iterator i = miLista.begin();
unsigned int precio;

if(strcmp(miNombre, nombre) == 0)
return miPrecio;
while(i!=miLista.end()) {
if(precio = (*i)->ObtenerPrecio(nombre))
return precio;
else { i++; }
}
return 0;
}; Componente * Compuesto::ObtenerHijo(const char *nombre) {
list <Componente *>::iterator i = miLista.begin();
Componente *Hijo;

if(strcmp(miNombre, nombre) == 0){ return this; }
while(i!=miLista.end()) {
Hijo = (*i)->ObtenerHijo(nombre);
if(Hijo) { return Hijo; }
else { i++; }
}
return 0;
};

void Compuesto::contenido() {
list <Componente *>::iterator i;
cout << " Compuesto: " << miNombre << endl;

for(i = miLista.begin(); i!=miLista.end(); i++)
(*i)->contenido();
}; Control de inserción en el ADD Jerarquía de compuestos compleja int main(void) {

//Construimos el árbol de compuestos
Compuesto c1("Torre", 40);
Compuesto c2("Placa Base", 90);
Pieza p1("DVD",30);
Pieza p3("Procesador",90);
Pieza p4("RAM",40);
Pieza p5("Disco Duro",80);
Pieza p6("T. Sonido",5);
Pieza p7("T. Grafica",5);
Componente *PC;
c1.Add(&c2);
c1.Add(&p1);
c1.Add(&p2);
c1.Add(&p3);
c1.Add(&p4);
c1.Add(&p5);
c2.Add(&p6);
c2.Add(&p7); Funciones extra Relación con otros patrones Control de modificación semántico Cadena de
responsabilidades Función búsqueda en cascada donde
se pide una cierta función y se recorren
objetos hasta que uno devuelva la función
pedida. Ejemplo: Objeto concreto para conectarme a internet. Una función en cascada recorrería objeto por objeto de un supuesto compuesto "piezas de ordenador" llamando al atributo "internet" hasta que uno de los objetos concretos devuelva un sí. //Puntero de tipo base apuntando a la raíz del árbol
PC = &c1;

//Operaciones:
//Mostrar todo el contenido del PC
PC->contenido();

//Calcular el precio total
cout << endl << "Precio total: " << PC->ObtenerPrecio();

//Obtener un precio específico
cout << "Precio RAM: " << PC->ObtenerPrecio("RAM")<< endl;

//Borrar un componente (compuesto o pieza)
c1.Remove(&c2);
PC->contenido();

char Salir;
cin >> Salir;
return 0;
} Con GetComposite se puede comprobar si un objeto es o no un compuesto. Ahora se pueden implementar de forma segura las operaciones de añadir y eliminar (Add y Remove) sobre el compuesto que se devuelve.

Composite *unCompuesto = new Composite;
Leaf *unaHoja = new Leaf;
Component *unComponente;
Composite *prueba;
unComponente = unCompuesto;
if (prueba = unComponente->GetComposite()) {
//Se está trabajando con un Compuesto, por
//tanto se le pueden añadir componentes (bien hojas, o
//bien compuestos).
prueba->Add(new Leaf);
}

unComponente = unaHoja;
if (prueba = unComponente->GetComposite()){
//Ahora se está tratando a una Hoja. La llamada
//a GetComposite retornará 0 en este caso. Se puede
//utilizar esto para asegurar que no se intenten
//añadir componentes a una Hoja.
prueba->Add(new Leaf);
} Decorator Se encarga de proveer de funcionalidades
extra a los objetos de una manera dinámica.
Agrega operaciones o estados.

Ejemplo: Asignar una propiedad nueva a un objeto
añadiendole un atributo. A un objeto concreto "perro"
bajo el compuesto "animal" agregamos a traves de la
herencia de la interface de Decorator un nuevo estado
que será "color = marron"

De esta manera el objeto no tiene que obtener todas
sus caracteristicas por herencia. En tiempo de
ejecucion se le pueden asignar nuevas, ergo es una alternativa a la herencia. FlyWeight Instancias de una clase que
contienen la misma información,
se puede establecer un grafo de
relaciones donde todos los objetos
concretos con esas características
tengan un enlace a ese nodo del grafo Crear elementos desde cero Iterator Se utiliza el patrón Iterator cuando una clase necesita acceder al contenido de una colección sin llegar a ser dependiente de la clase que es utilizada para implementar la colección, es decir, sin tener que exponer su representación interna. Por lo tanto, se puede utilizar el patrón Iterator para recorrer todos los hijos en un Composite Relación con otros patrones (1/2) Relaciones con otros
patrones (2/2) ¿? Información extra Integrantes EVOLUO Fernando M. Glez. Morales
Aniuska Mª Chacón Hdez
Patrick Herslink
Alberto Cruz Figuero esquema ejemplo
Full transcript