Volver a la página principal
sábado 13 julio 2024
18

Cómo implementar el Patrón Flyweight en TypeScript

Introducción

El patrón Flyweight es uno de los patrones de diseño estructurales propuestos por la "Gang of Four" (GoF). Su objetivo principal es minimizar el uso de memoria al compartir la mayor cantidad posible de datos entre objetos similares. Este patrón es especialmente útil cuando se necesitan crear una gran cantidad de objetos similares, lo que puede consumir una cantidad considerable de memoria.

En este artículo, exploraremos cómo implementar el patrón Flyweight en TypeScript. Veremos qué es el patrón Flyweight, cuándo es adecuado usarlo y proporcionaremos un ejemplo detallado de implementación en TypeScript.

¿Qué es el Patrón Flyweight?

El patrón Flyweight se basa en la idea de compartir datos comunes entre múltiples objetos para reducir el uso de memoria. En lugar de crear un nuevo objeto para cada instancia, compartimos partes del objeto que son inmutables y comunes a múltiples instancias. Estas partes compartidas se llaman "Flyweights".

Componentes del Patrón Flyweight

1. Flyweight: Define la interfaz que los flyweights concretos deben implementar.

2. ConcreteFlyweight: Implementa la interfaz de Flyweight y almacena los datos compartidos.

3. UnsharedConcreteFlyweight: Representa los objetos que no se comparten. Estos objetos pueden contener referencias a flyweights compartidos.

4. FlyweightFactory: Administra y crea flyweights. Asegura que los flyweights se compartan correctamente.

5. Client: Utiliza la fábrica para obtener instancias de flyweights y las utiliza.

Cuándo Usar el Patrón Flyweight

El patrón Flyweight es útil en las siguientes situaciones:

  • Cuando una aplicación utiliza una gran cantidad de objetos similares que podrían sobrecargar la memoria.
  • Cuando los objetos pueden dividirse en partes compartidas (inmutables) y no compartidas (mutables).
  • Cuando los objetos se crean y destruyen con frecuencia, lo que puede provocar problemas de rendimiento debido al manejo de la memoria.

Implementación en TypeScript

A continuación, se presenta un ejemplo de cómo implementar el patrón Flyweight en TypeScript. En este ejemplo, crearemos un sistema para gestionar figuras geométricas (círculos) con diferentes colores.

Paso 1: Definir la Interfaz Flyweight

Primero, definimos la interfaz Flyweight que las clases concretas implementarán.

interface Shape {
    draw(x: number, y: number): void;
}

Paso 2: Implementar ConcreteFlyweight

Implementamos la clase Circle, que será el flyweight concreto. Esta clase almacenará los datos compartidos (el color).

class Circle implements Shape {
    private color: string;

    constructor(color: string) {
        this.color = color;
    }

    draw(x: number, y: number): void {
        console.log(`Drawing a ${this.color} circle at (${x}, ${y})`);
    }
}

Paso 3: Implementar FlyweightFactory

La fábrica ShapeFactory será responsable de crear y gestionar los flyweights. Asegurará que los círculos con el mismo color se compartan.

class ShapeFactory {
    private static circles: { [key: string]: Circle } = {};

    public static getCircle(color: string): Circle {
        if (!this.circles[color]) {
            this.circles[color] = new Circle(color);
            console.log(`Creating a ${color} circle`);
        }
        return this.circles[color];
    }
}

Paso 4: Usar el Patrón Flyweight

Finalmente, utilizamos la fábrica para obtener los flyweights y dibujarlos.

function main() {
    const colors = ["Red", "Green", "Blue", "Yellow", "Black"];

    for (let i = 0; i < 20; i++) {
        const circle = ShapeFactory.getCircle(colors[Math.floor(Math.random() * colors.length)]);
        circle.draw(Math.floor(Math.random() * 100), Math.floor(Math.random() * 100));
    }
}

main();

Explicación del Código

1. Interfaz Shape: Define el método draw que todos los flyweights deben implementar.

2. Clase Circle: Implementa la interfaz Shape y almacena el color como un dato compartido.

3. Clase ShapeFactory: Gestiona la creación y el almacenamiento de los flyweights. Si un círculo con un color específico ya existe, se reutiliza.

4. Función main: Genera círculos aleatorios con colores aleatorios y los dibuja en posiciones aleatorias.

Salida Esperada

Al ejecutar el código anterior, deberíamos ver mensajes que indican cuándo se crean nuevos círculos y cuándo se reutilizan. Por ejemplo:

Creating a Red circle
Drawing a Red circle at (47, 58)
Creating a Green circle
Drawing a Green circle at (23, 75)
Drawing a Red circle at (93, 44)
...

En este ejemplo, podemos ver que se crean nuevos círculos solo cuando es necesario, y se reutilizan cuando ya existen, ahorrando memoria.

Conclusión

El patrón Flyweight es una técnica poderosa para optimizar el uso de memoria en aplicaciones que manejan una gran cantidad de objetos similares. En este artículo, hemos visto cómo implementar el patrón Flyweight en TypeScript mediante un ejemplo práctico de figuras geométricas. Este patrón es particularmente útil en aplicaciones donde la eficiencia y el rendimiento son cruciales. Implementarlo adecuadamente puede resultar en una reducción significativa del uso de memoria y una mejora en el rendimiento general de la aplicación.

Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer