# Design patterns: Flyweight

> Flyweight design pattern con esempi in PHP

- URL: https://mautoblog.com/posts/design-patterns/flyweight/
- Lingua: it
- Pubblicato: 2024-09-27
- Aggiornato: 2026-10-14
- Autore: Mauto
- Categorie: Sviluppo Software, Tecnologia
- Tags: Architettura Software, Best Practices, PHP
- Guida: Design Patterns (parte 12)
- Traduzione (en): https://mautoblog.com/en/posts/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
1. **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.
2. **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.
3. **Riuso degli Oggetti**: Facilita il riuso di oggetti simili, minimizzando la necessità di ricreare gli stessi dati più volte all'interno del sistema.
4. **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.
5. **Compromesso tra memoria e complessità**: Il risparmio di memoria ha un costo: separare lo stato intrinseco da quello estrinseco e gestire la condivisione tramite una factory aggiunge un po' di complessità al codice.

---

### Caso d'Uso
Supponiamo di dover gestire una vasta mappa di personaggi di un gioco, dove ogni personaggio ha un'icona ma poche informazioni variabili.
Invece di creare una nuova istanza dell'icona per ogni singolo personaggio, possiamo utilizzare il Flyweight Pattern per condividere le icone tra tutti i personaggi simili.

### Codice PHP
```php
// Flyweight - Oggetto condiviso
class CharacterIcon {
    private $icon; // Stato intrinseco (condiviso)

    public function __construct($icon) {
        $this->icon = $icon;
    }

    public function render($x, $y) {
        echo "Disegno l'icona '{$this->icon}' in posizione ($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];
    }

    public function countIcons() {
        return count($this->icons);
    }
}

// Client - Usa gli oggetti flyweight con stato estrinseco
class Game {
    private $iconFactory;
    private $characters = [];

    public function __construct() {
        $this->iconFactory = new CharacterIconFactory();
    }

    public function addCharacter($icon, $x, $y) {
        // Flyweight condiviso + stato estrinseco (posizione del personaggio)
        $this->characters[] = [
            'icon' => $this->iconFactory->getIcon($icon),
            'x' => $x,
            'y' => $y,
        ];
    }

    public function render() {
        foreach ($this->characters as $character) {
            $character['icon']->render($character['x'], $character['y']);
        }
        echo "Personaggi: " . count($this->characters) . ", icone condivise (flyweight): " . $this->iconFactory->countIcons() . "\n";
    }
}

// Utilizzo
$game = new Game();
$game->addCharacter('knight', 10, 20);
$game->addCharacter('knight', 15, 25);
$game->addCharacter('dragon', 30, 40);
$game->addCharacter('knight', 50, 60);
$game->render();
/*
Output:
Disegno l'icona 'knight' in posizione (10, 20)
Disegno l'icona 'knight' in posizione (15, 25)
Disegno l'icona 'dragon' in posizione (30, 40)
Disegno l'icona 'knight' in posizione (50, 60)
Personaggi: 4, icone condivise (flyweight): 2
*/
```

### 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** memorizza i personaggi: ognuno ha un riferimento all'icona condivisa e la propria posizione sulla mappa. Lo stato estrinseco (posizione) è variabile e non condiviso.
- Il metodo **render()** disegna tutti i personaggi e mostra quante icone ha creato la factory: 4 personaggi condividono solo 2 oggetti flyweight.

### 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.

[TORNA ALLA GUIDA](/posts/design-patterns/)
