Design patterns: Memento

Mauto 3 min

Il Memento Pattern è un pattern comportamentale che permette di catturare e salvare lo stato interno di un oggetto senza violarne l’incapsulamento, consentendo successivamente di ripristinare lo stato salvato. Questo pattern è utile quando si vuole implementare un sistema di undo/redo o per mantenere traccia degli stati passati di un oggetto.

Punti di Forza

  1. Salvataggio e Ripristino dello Stato: Consente di memorizzare lo stato interno di un oggetto e ripristinarlo in seguito, fornendo funzionalità di undo/redo in modo semplice ed efficace.
  2. Incapsulamento dello Stato: Mantiene l’incapsulamento dell’oggetto poiché il memento non rivela i dettagli dell’implementazione o lo stato interno dell’oggetto a cui è associato.
  3. Semplice Gestione degli Stati Complessi: Facilita la gestione di oggetti con stati complessi, permettendo di passare facilmente tra stati precedenti o successivi.
  4. Separazione delle Responsabilità: Il Memento Pattern separa la responsabilità di memorizzare lo stato (gestito dal memento) dalla logica aziendale dell’oggetto principale (gestito dall’originator).
  5. Indipendenza dal Client: Il client non ha bisogno di conoscere i dettagli di come gli stati vengono salvati e ripristinati. Deve solo gestire il memento come un oggetto opaco.

Caso d’Uso

Immaginiamo un editor di testo che permette di annullare le modifiche (funzione “undo”) grazie al Memento Pattern.

Codice PHP


//Classe `Editor` (Originator)
class Editor {
    private $content;

    public function setContent($content) {
        $this->content = $content;
    }

    public function getContent() {
        return $this->content;
    }

    // Creare un memento che memorizza lo stato corrente
    public function save() {
        return new EditorMemento($this->content);
    }

    // Ripristinare lo stato salvato da un memento
    public function restore(EditorMemento $memento) {
        $this->content = $memento->getContent();
    }
}

//Classe `Editor` (Originator)
class EditorMemento {
    private $content;

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

    public function getContent() {
        return $this->content;
    }
}

// Classe History (Caretaker)
class History {
    private $mementos = [];

    // Aggiungere un memento alla storia
    public function push(EditorMemento $memento) {
        $this->mementos[] = $memento;
    }

    // Ripristinare l'ultimo stato salvato
    public function pop() {
        if (!empty($this->mementos)) {
            return array_pop($this->mementos);
        }
        return null;
    }
}

// Utilizzo del Memento Pattern
$editor = new Editor();
$history = new History();

// Prima versione del contenuto
$editor->setContent("Prima versione del testo.");
$history->push($editor->save());

// Seconda versione del contenuto
$editor->setContent("Seconda versione del testo.");
$history->push($editor->save());

// Terza versione del contenuto
$editor->setContent("Terza versione del testo.");

echo "Contenuto attuale: " . $editor->getContent() . PHP_EOL;

// Ripristinare l'ultima versione salvata
$editor->restore($history->pop());
echo "Contenuto dopo l'undo: " . $editor->getContent() . PHP_EOL;

// Ripristinare la versione ancora precedente
$editor->restore($history->pop());
echo "Contenuto dopo un altro undo: " . $editor->getContent() . PHP_EOL;

/* Output
Contenuto attuale: Terza versione del testo.
Contenuto dopo l'undo: Seconda versione del testo.
Contenuto dopo un altro undo: Prima versione del testo.
*/

Conclusione

Il Memento Pattern è ideale quando hai bisogno di tenere traccia degli stati precedenti di un oggetto, come nei sistemi di undo/redo. Mantiene il principio dell’incapsulamento mentre semplifica la gestione di stati complessi, senza esporre i dettagli di implementazione agli altri componenti del sistema.

TORNA ALLA GUIDA

content_copy Copiato