Patrones de diseño estructurales: Flyweight

Intención del patrón
  • Comparte para soportar un gran número de objetos de grano fino de manera eficiente.
  • La estrategia de GUI Motif de reemplazo de widgets pesados por widgets livianos.


Ejemplo de problema
El diseño de los objetos hasta los niveles más bajos de granularidad del sistema proporciona una óptima flexibilidad, pero puede resultar inapropiadamente costosa en términos de rendimiento y uso de memoria.

Discusión
El patrón Flyweight describe cómo compartir objetos para permitir su uso en granularidad fina para sin costes excesivos. Cada objeto flyweight es dividido en dos partes: el estado dependiente (extrínseco) y el estado independiente (intrínseco). El estado intrínseco es almacenado (compartido) en el objeto Flyweight. El estado extrínseco es almacenado por el objeto cliente y pasado al objeto Flyweight, cuando sus operaciones son invocadas.
Un ejemplo de este enfoque serían los widgets Motif que han sido rediseñados como gadgets livianos. Mientras que los widgets son "inteligentes" como para valerse por sí mismos; los gadgets existen en una relación de dependencia con su widget controlador padre. Cada controlador proporciona un contexto dependiente de la gestión de eventos, estados y servicios de recursos para sus gadgets Flyweight y cada gadget es sólo responsable por el estado de contexto independiente y comportamiento.

Estructura
Los objetos Flyweight están almacenados en un repositorio de tipo Factory. El cliente se restringe de la crear directamente objetos Flyweight y lo solicita directamente al Factory. Cada objeto Flyweight no puede valerse por sí mismo. Cualquier atributo que pudiera hacer imposible compartir debe ser proporcionado por el cliente siempre que se realiza una solicitud al Flyweight. Si el contexto se presta para "economía a escala" (es decir, el cliente puede calcular o ver fácilmente los atributos necesarios), entonces el patrón Flyweight ofrece un apalancamiento apropiado.


las clases Ant, Lotus y Cockroach pueden ser "livianas" porque el estado de sus instancias específicas han sido desencapsuladas o expuestas y deben ser suministradas por el cliente.


Ejemplo
El patrón Flyweight comparte para soportar un gran número de objetos de manera eficiente. La red pública de conmutadores telefónicos es un ejemplo de este patrón. Hay gran cantidad de recursos tales como generadores de tono de marcado, generadores de llamada y receptores de dígitos que deben ser compartidos entre todos los suscriptores. Un suscriptor no tiene conocimiento de cuantos recursos se encuentran en el pool cuando él o ella levanta el auricular para realizar una llamada. Todo lo que le importa a los suscriptores es que se les proporcione el tono de marcado, que los dígitos sean recibidos y que la llamada sea realizada.


Check list

  1. Asegurarse que la sobrecarga de objeto es un tema que necesita atención y el cliente de la clase es capaz y está dispuesto a absorber la responsabilidad de reajuste.
  2. Dividir la clase de estado de destino en: Estado compartible (intrínseco) y estado no compartible (extrínseco).
  3. Quitar el estado no compartible de los atributos de clase y agregarlo como argumento de llamada a la lista de métodos afectados.
  4. Crear un Factory que pueda almacenar en caché y reutilizar instancias de clases existentes.
  5. El cliente debe usar el Factory en lugar del operador new.
  6. El cliente (o un tercero) debe observar o calcular el estado no compartible y suministrar el estado a través de métodos de clase.


Reglas de oro
Mientras el patrón Flyweight muestra cómo hacer gran cantidad de pequeños objetos, Facade cómo hacer un único objeto representativo de un subsistema completo.
Flyweight es a menudo combinado con Composite para implementar nodos compartidos.
Flyweight explica cómo y cuándo objetos State pueden ser compartidos.

Ejemplo de código C#
using System;
using System.Collections;

class MainApp
{
  static void Main()
  {
    // Arbitrary extrinsic state 
    int extrinsicstate = 22;

    FlyweightFactory f = new FlyweightFactory();

    // Work with different flyweight instances 
    Flyweight fx = f.GetFlyweight("X");
    fx.Operation(--extrinsicstate);

    Flyweight fy = f.GetFlyweight("Y");
    fy.Operation(--extrinsicstate);

    Flyweight fz = f.GetFlyweight("Z");
    fz.Operation(--extrinsicstate);

    UnsharedConcreteFlyweight uf = new 
      UnsharedConcreteFlyweight();

    uf.Operation(--extrinsicstate);

    // Wait for user 
    Console.Read();
  }
}

// "FlyweightFactory" 
class FlyweightFactory 
{
  private Hashtable flyweights = new Hashtable();

  // Constructor 
  public FlyweightFactory()
  {
    flyweights.Add("X", new ConcreteFlyweight());    
    flyweights.Add("Y", new ConcreteFlyweight());
    flyweights.Add("Z", new ConcreteFlyweight());
  }

  public Flyweight GetFlyweight(string key)
  {
    return((Flyweight)flyweights[key]); 
  }
}

// "Flyweight" 
abstract class Flyweight 
{
  public abstract void Operation(int extrinsicstate);
}

// "ConcreteFlyweight" 

class ConcreteFlyweight : Flyweight
{
  public override void Operation(int extrinsicstate)
  {
    Console.WriteLine("ConcreteFlyweight: " + extrinsicstate);
  }
}

// "UnsharedConcreteFlyweight" 
class UnsharedConcreteFlyweight : Flyweight
{
  public override void Operation(int extrinsicstate)
  {
    Console.WriteLine("UnsharedConcreteFlyweight: " + 
      extrinsicstate);
  }
}

0 comentarios:

Publicar un comentario

Muchas gracias por leer el post y comentarlo.

 
Copyright 2009 Programación SOLIDa
BloggerTheme by BloggerThemes | Design by 9thsphere