El patrón de diseño Flyweight
Descripción
El objetivo del patrón de diseño Flyweight es compartir de forma eficaz un conjunto importante de objetos de granularidad fina.
Ejemplo
En el sistema de venta de vehículos, es necesario administrar las opciones que el comprador puede elegir cuando está comprando un nuevo vehículo. Estas opciones están descritas por la clase OpcionVehiculo.
Por cada vehículo solicitado, es posible asociar una nueva instancia de esta clase. No obstante a menudo existe un gran número de opciones para cada vehículo solicitado, lo cual obliga al sistema a gestionar un conjunto enorme de objetos sencillos y, por tanto, de pequeño tamaño (de granularidad fina). Este enfoque presenta sin embargo la ventaja de poder almacenar a nivel de opción la información específica a la propia opción y al vehículo, como por ejemplo el precio de venta de la opción, que puede diferir de un vehículo a otro.
Esta solución se presenta con un ejemplo en la figura 15.1 y es fácil darse cuenta de que es necesario gestionar un gran número de instancias de OpcionVehiculo porque muchas de ellas contienen datos idénticos.
Figura 15.1 - Ejemplo de ausencia de compartición en objetos de granularidad fina
El patrón de diseño Flyweight proporciona una solución a este problema compartiendo las opciones:
-
La compartición se realiza mediante una fábrica a la que el sistema se dirige para obtener una referencia hacia una opción. Si esta opción no se ha creado hasta ahora...
Estructura
1. Diagrama de clases
La figura 15.3 detalla la estructura genérica del patrón de diseño Flyweight.
Figura 15.3 - Estructura del patrón de diseño Flyweight
2. Participantes
Los participantes del patrón de diseño Flyweight son los siguientes:
-
FabricaFlyweight (FabricaOpcion) crea y administra los objetos peso mosca. La fábrica se asegura de que estos se comparten gracias al método getFlyweight que devuelve sus referencias.
-
Flyweight (OpcionVehiculo) mantiene el estado intrínseco e implementa los métodos. Estos métodos reciben y determinan a su vez el estado extrínseco de los objetos peso mosca.
-
Cliente (VehiculoSolicitado) contiene un conjunto de referencias hacia los objetos peso mosca que utiliza. El cliente debe a su vez guardar el estado extrínseco de estos objetos.
3. Colaboraciones
Los clientes no deben crear ellos mismos los objetos peso mosca, sino utilizar el método getFlyweight de la fábrica FabricaFlyweight que garantiza que las instancias se comparten.
Cuando un cliente invoca un método de un peso mosca, debe transmitirle su estado extrínseco.
Dominio de aplicación
El dominio de aplicación del patrón de diseño Flyweight es la posibilidad de compartir pequeños objetos (pesos mosca). Los criterios de uso son los siguientes:
-
El sistema utiliza un gran número de objetos de granularidad fina y su almacenamiento es costoso.
-
Existen numerosos conjuntos de objetos que pueden reemplazarse por algunos objetos compartidos una vez que parte de su estado se vuelve extrínseco.
Ejemplo en PHP
La clase OpcionVehiculo posee un constructor que permite definir el estado intrínseco de la opción. Este estado se limita a una cadena de caracteres que almacena su nombre.
El método visualiza recibe como parámetro una matriz compuesta por el precio de venta de la opción y su referencia en el catálogo, que constituye el estado extrínseco del objeto.
<?php
declare(strict_types=1);
namespace ENI\DesignPatterns\Flyweight;
class OpcionVehiculo
{
protected string $nombre;
public function __construct(string $nombre)
{
$this->nombre = $nombre;
}
public function visualiza(array $contexto): void
{
echo 'Opción' . PHP_EOL;
echo 'Nombre: ' . $this->nombre . PHP_EOL;
foreach ($contexto as $clave => $valor) {
echo ucfirst($clave) . ': ' . $valor . PHP_EOL;
}
}
}
La clase FabricaOpcion gestiona...