Design patterns: Flyweight
Il Flyweight Pattern è un pattern strutturale utilizzato per ridurre il consumo di memoria e migliorare l’efficienza nelle applicazioni che devono gestire un gran numero di oggetti simili. L’idea principale è quella di condividere oggetti comuni (flyweight) tra più entità, evitando duplicazioni non necessarie. Gli oggetti “flyweight” immutabili sono condivisi mentre le parti variabili vengono gestite separatamente.
Caratteristiche del Flyweight pattern
- Riduzione dell’Uso della Memoria: Permette di ridurre drasticamente la quantità di memoria utilizzata, condividendo tra più entità gli oggetti che presentano proprietà comuni e immutabili.
- Efficienza: Il pattern migliora l’efficienza quando vengono creati e gestiti grandi volumi di oggetti, specialmente in contesti in cui gli oggetti hanno solo alcune differenze minori tra loro.
- Riuso degli Oggetti: Facilita il riuso di oggetti simili, minimizzando la necessità di ricreare gli stessi dati più volte all’interno del sistema.
- Separazione tra Stato Intrinseco ed Estrinseco: Lo stato intrinseco (immutabile e condiviso) è separato dallo stato estrinseco (specifico per l’istanza). Questo consente una gestione più efficiente degli oggetti.
- Manutenibilità: Il codice risulta più manutenibile e leggibile, poiché centralizza la creazione di oggetti simili, riducendo la complessità del sistema.
Caso d’Uso
Supponiamo di dover gestire una vasta mappa di caratteri di un gioco, dove ogni carattere ha un’icona ma poche informazioni variabili. Invece di creare una nuova istanza di ogni singolo carattere, possiamo utilizzare il Flyweight Pattern per condividere le icone tra tutti i caratteri simili.
Codice PHP
// Flyweight - Oggetto condiviso
class CharacterIcon {
private $icon; // Stato intrinseco (condiviso)
public function __construct($icon) {
$this->icon = $icon;
}
public function render($x, $y) {
echo "Rendering icon '{$this->icon}' at position ($x, $y)\n";
}
}
// Flyweight Factory - Gestisce la condivisione degli oggetti
class CharacterIconFactory {
private $icons = [];
public function getIcon($icon) {
if (!isset($this->icons[$icon])) {
$this->icons[$icon] = new CharacterIcon($icon);
}
return $this->icons[$icon];
}
}
// Client - Usa gli oggetti flyweight con stato estrinseco
class Game {
private $iconFactory;
public function __construct() {
$this->iconFactory = new CharacterIconFactory();
}
public function addCharacter($icon, $x, $y) {
$characterIcon = $this->iconFactory->getIcon($icon);
$characterIcon->render($x, $y); // Stato estrinseco: posizione del carattere
}
}
// Utilizzo
$game = new Game();
$game->addCharacter('knight', 10, 20);
$game->addCharacter('knight', 15, 25);
$game->addCharacter('dragon', 30, 40);
$game->addCharacter('knight', 50, 60);
Spiegazione
- CharacterIcon rappresenta lo stato intrinseco (immutabile) che viene condiviso tra tutti i personaggi dello stesso tipo.
- CharacterIconFactory gestisce la creazione e condivisione degli oggetti CharacterIcon per evitare di creare duplicati.
- Game gestisce la creazione dei personaggi, assegnando loro icone e posizionandoli sulla mappa. Lo stato estrinseco (posizione) è variabile e non condiviso.
Conclusione
Il Flyweight Pattern è ideale quando si ha a che fare con un numero elevato di oggetti simili che condividono molte proprietà comuni, consentendo un risparmio significativo di memoria e migliorando le performance dell’applicazione.