Patrón de Diseño: Flyweight

ABSTRACT— Flyweight is a software design pattern. A Flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory. Often some parts of the object state can be shared and it's common to put them in external data structures and pass them to the flyweight objects temporarily when they are used.

INTRODUCCION

Los patrones estructurales están relacionados con cómo las clases y los objetos se combinan para dar lugar a estructuras más complejas. Puede hacerse la distinción de patrones estructurales asociados a clases y asociados a objetos, los primeros utilizarán la herencia, los segundos la composición.
Los patrones estructurales asociados con objetos describen formas de componer los objetos para conseguir nueva funcionalidad. La flexibilidad de la composición de objetos viene de la posibilidad de cambiar la composición en tiempo de ejecución, lo que es imposible con la composición estática de clases. En el presente documento se da a conocer uno de los patrones de diseño asociado a objetos llamado FLYWEIGHT.

I. PATRÓN DE DISEÑO: FLYWEIGHT

A continuación se encuentra la plantilla del patrón objeto de estudio:

1. Nombre del patrón: Flyweight.

2. Clasificación del patrón: Estructural.

3. Intención: Compartir estados para soportar un gran número de objetos pequeños aumentando la eficiencia en espacio.

4. También conocido como: Peso ligero.

5. Motivación:

El patrón flyweight describe como almacenar un gran número de objetos sin un gran coste.
Para conseguir esto se utilizan objetos que almacenan los estados compartidos y que pueden ser usados por varios objetos simultáneamente.

Estado intrínseco y extrínseco
El estado intrínseco es almacenado en el objeto.
El estado extrínseco es pasado (contexto) como parámetro en las operaciones.

6. Aplicabilidad:

Este patrón se usa cuando:

•Se utiliza un gran número de objetos
•El coste de almacenamiento es alto debido a la cantidad de objetos
•La mayoría de los estados de los objetos pueden ser creados como comunes.
•Muchos objetos pueden ser reemplazados por unos pocos una vez que han sido borrados los estados no comunes.
•La aplicación no depende de la identidad de los objetos.

7. Estructura:




8. Participantes:

Flyweight: Declara una interfaz a través de la cual los flyweights pueden recibir y actuar sobre los estados no compartidos.
ConcreteFlyweight: Implementa la interfaz Flyweight y almacena los estados compartidos, si los hay. Un objeto ConcreteFlyweight debe ser compartible. Cualquier estado que almacene debe ser intrínseco; es decir, debe ser independiente de su contexto.
Client: Contiene referencias a los flyweights. Calcula o almacena los estados no compartidos de los flyweights.
UnsharedConcreteFlyweight: No todas las subclases de Flyweight tienen por qué ser compartidas. La interfaz Flyweight permite que se comparta; no lo fuerza. Es común que los objetos de esta clase tengan hijos de la clase ConcreteFlyweight en algún nivel de su estructura.
FlyweightFactory: Crea y gestiona los objetos flyweight. Garantiza que los objetos flyweight se comparten de forma apropiada. Cuando un cliente solicita un flyweight, el objeto de la clase FlyweightFactory proporciona una instancia existente, o crea una.

9. Colaboraciones:

Un objeto flyweight debe ser clasificado como compartido o no compartido. Los compartidos se almacenan en el objeto ConcreteFlyweight; los no compartidos se almacenan o se calculan en el objeto Cliente. Los clientes pasan este estado al objeto flyweight cuando invocan sus operaciones.
Los clientes no deberían instanciar objetos de la clase ConcreteFlyweight directamente. Deben obtenerlos exclusivamente del objeto FlyweightFactory para garantizar que son compartidos apropiadamente.


10. Consecuencias:

Ventajas:

•Ahorro de espacio
o Por la reducción en el número de instancias
o Por la reducción en el estado intrínseco
o Por la reducción en el estado extrínseco (si es computado)
o Reduce en gran cantidad el peso de los datos en un servidor

•Los Flyweight suelen ser hojas compartidas en los Composite. La compartición impide que en los Composite se almacenen enlaces a los padres

 Desventajas: Coste temporal de computar y/o transmitir el estado extrínseco.

11. Implementación:

•Asegúrese que el rendimiento en los objetos es un tema primordial, y si el cliente está dispuesto a asumir el reajuste.
•Divida el objetivo principal en estados: Estado Intrínseco (elementos que se puedan compartir o son comunes) y Estado Extrínseco (elementos particulares a cada tipo).
•Retire los elementos con estado extrínseco de los atributos de la clase, y añádale más bien una llamada a métodos.
•Crear una fábrica que pueda almacenar y rehusar las instancias existentes de clases.
•El cliente debe usar la fábrica en vez de utilizar el operador new si requiere de creación de objetos.
•El cliente (o un tercero) debe revisar los estados extrínsecos, y reemplazar esos estados a métodos de la clase.

12. Código de ejemplo:

public abstract class CreaLetra {
public abstract void asignaLetra(Letra letra);
}
public class Letra {
private char letra;
public Letra(char letra) {
this.setLetra(letra);
}
public char getLetra() {
return this.letra;
}
private void setLetra(char letra) {
this.letra=letra;
}
}

public class Formato extends CreaLetra{
private String tipo;
private int tam;
public Formato(String tipo,int tam) {
this.setTipo(tipo);
this.setTam(tam);
}

public void asignaLetra(Letra letra) {
System.out.println( "Tipo de letra " + this.getTipo() + " con tamaño: " + this.getTam() +" para la letra " + letra.getLetra());
}
public boolean equals(Object obj) {
return this.getTipo().equals(((Formato)obj).getTipo()) & this.getTam()==((Formato)obj).getTam();
}
}

public class FormatoFactory {
private CreaLetra[] formatos;
private int creados;
public FormatoFactory() {
this.formatos=new Formato[100];
this.setCreados(0);
}
public int getCreados() {
return this.creados;
}
private void setCreados(int creados) {
this.creados=creados;
}
public CreaLetra getFormato(String tipo, int tam) {
CreaLetra tmp = new Formato(tipo,tam);
if (this.getCreados() > 0) {
for (int i = 0; i < getCreados(); i++) {
if (tmp.equals(formatos[i])) {
return formatos[i];
}
}
}
formatos[this.getCreados()] = tmp;
this.setCreados(this.getCreados()+1);
return formatos[this.getCreados()-1];
}
}


public class TestFlyweight {
private CreaLetra[] formatos;
private Letra[] letras;
private FormatoFactory formatoFactory;
private int numLetras;
public TestFlyweight() {
this.formatos = new Formato[100];
this.letras = new Letra[100];
this.formatoFactory = new FormatoFactory();
this.setNumLetras(0);
}

public void recibirLetra(String tipo, int tam, char letra){
formatos[this.getNumLetras()] = formatoFactory.getFormato(tipo,tam);
letras[this.getNumLetras()] = new Letra(letra);
this.setNumLetras(this.getNumLetras()+1);
}
public void runTest() {
this.recibirLetra("Arial",10,'a');
this.recibirLetra("Arial",10,'b');
this.recibirLetra("Times",11,'c');
this.recibirLetra("Times",11,'d');
this.recibirLetra("Comic",11,'e');
this.recibirLetra("Comic",11,'f');
this.recibirLetra("Arial",10,'g');
this.recibirLetra("Arial",10,'h');
this.recibirLetra("Times",10,'i');
this.recibirLetra("Times",10,'j');
this.recibirLetra("Arial",11,'k');
this.recibirLetra("Arial",11,'l');
for (int i = 0; i < this.getNumLetras(); i++){
formatos[i].asignaLetra(letras[i]);
}
System.out.println("");
System.out.println("Número total de formatos creados: " + formatoFactory.getCreados());
}
}

Public class Cliente{
public static void main(String[] args) {
TestFlyweight test = new TestFlyweight();
test.runTest();
}
}


13. Usos Conocidos:
Librerias de fuentes de office.
Un clásico ejemplo de uso del flyweight son el patrón de estructuras de datos para la representación gráfica de los caracteres en un procesador de textos.

14. Patrones relacionados:

Composite, utilizado para componer objetos en estructural de árbol para representar jerarquías.
Proxy, que proporciona un intermediario de otro objeto para controlar el acceso a este.
Facade, que proporciona una interfaz unificada para un conjunto de interfaces de un subsistema.


REFERENCIAS
[1] García Pérez Baltasar. Desarrollo rápido de aplicaciones. Version PDF.
[2] Orjuela Luz Marina. Modelos de Programación: Patrones GOF 10. Universidad Distrital Francisco José de Caldas. 2006.
[3] Cuesta Carlos E. Patrones de Diseño. Ingeniería de software I. Universidad Rey Juan Carlos. Versión PDF.
[4] Herrera Mauricio, Navia Andrés. Bridge, Builder & Interpreter. Versión PDF.
[5] http://www.info-ab.uclm.es/asignaturas/42579/cap4/Estructural.htm
[6] http://es.wikipedia.org/wiki/Flyweight_(patr%C3%B3n_de_dise%C3%B1o)
[7] http://msdn.microsoft.com/es-es/library/bb972240.aspx#XSLTsection124121120120
[8] http://gaia.fdi.ucm.es/people/pedro/das02/23flyweight.pdf
[9] http://en.wikipedia.org/wiki/Flyweight_pattern
[10] http://www.exciton.cs.rice.edu/javaresources/DesignPatterns/FlyweightPattern.htm
[11] http://www.developer.com/tech/article.php/3677501

No hay comentarios:

Publicar un comentario