# Design patterns: Prototype

> Prototype design pattern con esempi in PHP

- URL: https://mautoblog.com/posts/design-patterns/prototype/
- 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 6)
- Traduzione (en): https://mautoblog.com/en/posts/design-patterns/prototype/

---
Il pattern Prototype è un pattern creazionale che permette di creare nuovi oggetti clonando un'istanza esistente. 
Questo è utile quando la creazione di un nuovo oggetto richiede risorse significative e possiamo ottenere nuove istanze clonando quelle esistenti.

## Caratteristiche del pattern prototype
1. **Creazione di Oggetti tramite clonazione:** Il Prototype Pattern consente di creare nuovi oggetti copiando (clonando) un oggetto esistente, anziché istanziarlo tramite un costruttore. Questo è particolarmente utile per oggetti complessi.
2. **Indipendenza dei cloni:** Gli oggetti prototipo possono essere utilizzati come basi per la creazione di nuovi oggetti. I nuovi oggetti creati tramite clonazione possono essere modificati senza alterare l'oggetto prototipo originale. Attenzione: in PHP `clone` esegue una copia superficiale, quindi le proprietà che contengono oggetti vanno clonate esplicitamente in `__clone()` (deep copy), altrimenti clone e prototipo le condividono.
3. **Indipendenza dalla Classe concreta:** Il pattern non richiede che il codice client conosca la classe concreta degli oggetti che sta creando. Può interagire con gli oggetti attraverso un'interfaccia comune.
4. **Semplificazione della Creazione di Oggetti complessi:** Quando un oggetto è difficile o costoso da creare, il Prototype Pattern permette di definire un oggetto "modello" che può essere clonato e personalizzato.
5. **Efficienza:** Clonare un oggetto può essere più efficiente rispetto alla creazione di un nuovo oggetto, specialmente se il processo di costruzione è complesso e richiede molte risorse.
6. **Supporto per la Variazione Dinamica:** È facile cambiare la configurazione di un oggetto copiato senza influenzare il prototipo originale, consentendo flessibilità nella gestione degli oggetti durante l'esecuzione.
7. **Minor dipendenza da Costruttori:** Riduce la necessità di utilizzare diversi costruttori per vari oggetti, semplificando il codice e migliorando la manutenibilità.

### Esempio in PHP:
Immaginiamo di avere un sistema in cui possiamo creare diversi tipi di animali clonandoli a partire da prototipi conservati in un registro.

```php
// Interfaccia Prototype
interface AnimalPrototype {
    public function __clone();
    public function getType();
    public function getName();
    public function setName($name);
}

// Classe Concreta per Pecora
class Sheep implements AnimalPrototype {
    private $type = "Pecora";
    private $name;

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

    public function getType() {
        return $this->type;
    }

    public function getName() {
        return $this->name;
    }

    public function setName($name) {
        $this->name = $name;
    }

    public function __clone() {
        // Le proprietà scalari vengono copiate automaticamente.
        // Eventuali proprietà oggetto andrebbero clonate qui (deep copy).
    }
}

// Classe Concreta per Mucca
class Cow implements AnimalPrototype {
    private $type = "Mucca";
    private $name;

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

    public function getType() {
        return $this->type;
    }

    public function getName() {
        return $this->name;
    }

    public function setName($name) {
        $this->name = $name;
    }

    public function __clone() {
        // Le proprietà scalari vengono copiate automaticamente.
        // Eventuali proprietà oggetto andrebbero clonate qui (deep copy).
    }
}

// Registro che conserva i prototipi e restituisce cloni
class AnimalRegistry {
    private $prototypes = [];

    public function addPrototype($key, AnimalPrototype $prototype) {
        $this->prototypes[$key] = $prototype;
    }

    public function create($key): AnimalPrototype {
        if (!isset($this->prototypes[$key])) {
            throw new InvalidArgumentException("Prototipo non trovato: $key");
        }
        return clone $this->prototypes[$key];
    }
}

// Configurazione: i prototipi vengono creati una sola volta
$registry = new AnimalRegistry();
$registry->addPrototype("pecora", new Sheep("Dolly"));
$registry->addPrototype("mucca", new Cow("Carolina"));

// Utilizzo: il client chiede un clone al registro, senza usare "new"
$firstSheepClone = $registry->create("pecora");
$secondSheepClone = $registry->create("pecora");
$firstCowClone = $registry->create("mucca");

// Modifichiamo un clone: il prototipo non cambia
$secondSheepClone->setName("Shaun");

echo "Clonata: " . $firstSheepClone->getType() . " " . $firstSheepClone->getName() . "\n"; // Clonata: Pecora Dolly
echo "Clonata: " . $secondSheepClone->getType() . " " . $secondSheepClone->getName() . "\n"; // Clonata: Pecora Shaun
echo "Clonata: " . $firstCowClone->getType() . " " . $firstCowClone->getName() . "\n"; // Clonata: Mucca Carolina
echo "Prototipo invariato, nuovo clone: " . $registry->create("pecora")->getName() . "\n"; // Prototipo invariato, nuovo clone: Dolly
```
[TORNA ALLA GUIDA](/posts/design-patterns/)
