5: Quinto patrón de diseño - FranzBurneo/Patrones-de-dise-o GitHub Wiki
Flyweight
Flyweight pertenece a los patrones de diseño estructural, este patrón permite colocar más objetos en la RAM disponible, esto se hace compartiendo partes comunes de estado entre varios objetos en lugar de mantener todos los datos en cada objeto. Además utiliza la estrategia de Motif GUI de reemplazar widgets pesados con dispositivos livianos.
Problema
Diseñar los objetos hasta los niveles más bajos de "granularity" del sistema proporciona una flexibilidad óptima, pero como resultado nos devuelve un muy alto precio en términos de rendimiento y uso de memoria
Usabilidad
Este patrón utiliza el uso compartido para admitir una gran cantidad de objetos de manera eficiente. Esta ventaja la hace uso los navegadores web modernos, debido a que utilizan esta técnica para cargar las mismas imágenes más de una vez. Cuando el navegador carga una página, recorre todas las imágenes de esa página. El navegador carga todas las imágenes nuevas de Internet y las coloca en el caché interno. Para las imágenes ya cargadas, se crea un objeto de Flyweight el cual tiene algunos datos únicos como la posición en la página, pero todo lo demás está referenciado al almacenado en caché.
Estructura
Los Flyweight se alamacenan en el repositorio de un Factory. El cliente no crea los Flyweights pero los solicita a Factory. Cada Flyweight no se puede sostener por sí solo. Cualquier atributo que hace imposible compartirlo debe ser proporcionado por el cliente siempre que se haga una solicitud de Flyweight. Si el contexto se presta a una "economy of scale" (el cliente puede calcular o buscar los atributos necesarios), entonces el patrón Flyweight ofrece el aplacamiento adecuado.
Los Ant, Locust y Cockroach las clases pueden ser "ligero" debido a que su estado de la instancia especígica ha sido de-encapsulated, o exterioriza, y deben ser suministrados por el cliente.
Ejemplo
Se utiliza el uso compartido para admitir una gran cantidad de objetos detallados de manera eficiente
import abc
class FlyweightFactory:
Cree y administre objetos de Flyweight. Asegúrese de que los Flyweights se compartan correctamente. Cuando un cliente solicita un Flyweight, el objeto FlyweightFactory proporciona una instancia existente o crea una, si no existe ninguna.
def __init__(self):
self._flyweights = {}
def get_flyweight(self, key):
try:
flyweight = self._flyweights[key]
except KeyError:
flyweight = ConcreteFlyweight()
self._flyweights[key] = flyweight
return flyweight
class Flyweight(metaclass=abc.ABCMeta):
Declaramos una interfaz a través de la cual los Flyweight puedan recibir y actuar en estado extrínseco.
def __init__(self):
self.intrinsic_state = None
@abc.abstractmethod
def operation(self, extrinsic_state):
pass
class ConcreteFlyweight(Flyweight):
Se implementa la interfaz Flyweight y se agrega almacenamiento para el estado intrínseco, si lo hay. Un objeto ConcreteFlyweight debe poder compartirse. Ningun estado almacenado debe ser intrínseco; es decir, debe ser independiente del contexto del objeto ConcreteFlyweight.
def operation(self, extrinsic_state):
pass
def main():
flyweight_factory = FlyweightFactory()
concrete_flyweight = flyweight_factory.get_flyweight("key")
concrete_flyweight.operation(None)
if __name__ == "__main__":
main()