PHP: cómo y cuando usar el patrón de Peso Mosca o Flyweight

2022-02-02 - Categorías: General / PHP / Principios y patrones

Este patrón del diseño del software es un patrón para optimizar los recursos, para reducir el coste espacial, y probablemente también el coste temporal de nuestros programas. El patrón Flyweight o Peso Mosca se basa en la optimización de recursos disminuyendo la cantidad de información que tiene cada objeto.

Es decir, cuando tenemos muchos objetos similares con información muy parecida, conviene desacoplar la información común y agruparla en nuevos objetos, reduciendo los originales.

Al grano, un caso de estudio en PHP

Por ejemplo, supongamos que tenemos que trabajar con muchos coches que tienen texturas. La textura es algo que se repite y puede ocupar bastante espacio en memoria. Con lo que si almacenamos los datos de cada textura en cada coche, ocuparán más memoria que si simplemente almacenamos un identificador a cada textura en cada coche.

Entonces, almacenamos las texturas en clases distintas y usamos una fábrica de texturas para obtener los datos de cada una.

Además, la fábrica puede crear la textura en memoria si todavía no lo está, y devolver los datos de la que exista creada evitando crear dos texturas iguales usando el patrón Singleton.

Un esquema posible:

Patrón Flyweight o Peso Mosca

Ahora supongamos por ejemplo un Main en PHP, que crea un conjunto de 100 coches con texturas random, y los devuelve al front para pintarlos en JavaScript:

<?php

class Main
{
    public $cars = [];
    public $textures = [];
    public $textureFactory;

    public function main()
    {
        $this->textureFactory = new TextureFactory();

        for ($i = 0; $i < 100; ++$i) {
            $newCar = new Car();
            // Random texture foreach car..
            $newCar->textureID = 'Texture'.rand(1, 3);
            $cars[] = $newCar;
        }

        foreach ($cars as $car) {
            // If not isset this texture, retrive the data from the factory..
            if (!isset($this->textures[$car->textureID])) {
                $this->textures[$car->textureID] = $this->textureFactory->getTexture($car->textureID)->getTextureData();
            }
        }

        /*
        * Do something with textures and cars, for instance, return them to render in the front..
        */
    }
}

..esto podría ser un comienzo de fábrica de texturas:

<?php

class TextureFactory
{
    /**
     * Here it can receive $textureID = Texture1|Texture2|Texture3.
     */
    public function getTexture($textureID): ITexture
    {
        // This can be made using Singletones
        // for a better performance..
        $texture = new $textureID();

        return $texture;
    }
}

..un coche que sólo almacena su posición y el identificador de su textura:

<?php

class Car
{
    public $textureID;
    public $x;
    public $y;
}

..una interfaz para definir el contrato de funciones que tiene que tener cada textura nueva:

<?php

interface ITexture
{
    public function getTextureData();
}

..y una posible implementación para cada textura:

<?php

class Texture1 implements ITexture
{
    public function getTextureData()
    {
        /*
         * Here we return the data of this texture..
         */
    }
}
<?php

class Texture2 implements ITexture
{
    public function getTextureData()
    {
        /*
         * Here we return the data of this texture..
         */
    }
}
<?php

class Texture3 implements ITexture
{
    public function getTextureData()
    {
        /*
         * Here we return the data of this texture..
         */
    }
}

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

 

© 2022 JnjSite.com - MIT license

Sitio hecho con WordPress, diseño y programación del tema por Jnj.