Memento – обект, който служи само за да съхранява ЕДНА „моментна снимка“ (shapshot) на обект, който ще наричаме Originator.
И отделните Memento обекти („mementos“ на Originator обектът) могат от своя страна да бъдат организирани като масив например, където да се трупат и достъпват.
A memento is an object that stores a snapshot of the internal state of another object—the memento’s originator.
Много важно е Memento класът да не допуска друг клас освен Originator да има достъп до отделните запазени състояния (snaphots), демек Originator-ът сам да си управлява така да се каже „миналите състояния“.
Също, класът Memento трябва да има поне една двойка публични сетър/гетър методи, които Orginator да вика, за да може да вземе текущото състояние на данните на Memento, както и да може да възстанови някои от предишните такива. Това ще са така да се каже „прозорци“ на Memento класа.
Да не забравяме, че принципите data hiding и capsulation трябва да се спазват.
Originator – това ще е обектът, на който ще запазваме отделните състояния.
Only the originator can store and retrieve information from the memento, the memento is „opaque“ to other objects.
Оригинаторът ще има един метод (напр. „saveToMemento()“), в който ще се създава обект Memento, на който пък се подава дадената информация (моментна снимка), която ще искаме да съхраним.
Ще има съответно и метод (напр. „restoreFromMemento()“), който ще приема даденото „мементо“, което искаме да възстановим.
CareTaker – това е класът, който ще използваме като „шкафче“ и където ще пазим отделните mementos, например като масив. Originator ще използва този клас за да добавя/извилича отделните mementos.
CareTaker не се интересува и не работи по никакъв начин с информацията, съхранена в него, само я съхранява, добавя и изважда от „шкафчето“ за да я върне на Originator.
Прост пример:
<?php /** * Това ще ни е класът, на когото ще пазим отделните "моментни снимки" * с оглед на това да можем да възстановяваме * когато ни трябва. Тоест, заради него ще прилагаме самият Memento Design Pattern. * Съществените методи са "saveToMemento()" и "restoreFromMemento()" */ class Originator { private string $state; // The class could also contain additional data that is not part // of the Memento Design Pattern public function set(string $state) : void { $this->state = $state;printf("%s\n\n", 'Originator: Setting state to ' . $state);
} public function saveToMemento() : Memento { printf("%s\n\n", 'Originator: Saving to Memento.');return new Memento($this->state);
} public function restoreFromMemento(Memento $memento) : void { $this->state = $memento->getSnapshot();printf("%s\n\n", 'Originator: State after restoring from Memento: ' . $this->state);
} } /** * Този клас ще играе ролята на една прост data container, всеки обект * от който ще е просто една "моментна снимка", * по този начин информацията ("моментната снимка") ще е "скрита" от * околният свят (data hidding). */ class Memento { private string $snapshot; public function __construct(string $snapshotToSave) { $this->snapshot = $snapshotToSave; } public function getSnapshot() : string { return $this->snapshot; } } /** * Това ще е така да се каже "диригентът" на това да създаваме моментни снимки, * и да можем да ги възстановяваме. */ class Caretaker { private array $savedStates = array(); // This will be the array with the mementos private Originator $originator; public function __construct(Originator $originator) { $this->originator = $originator; } public function takeCare() : void { $this->originator->set("State 1");$this->originator->set("State 2");
// Push a memento, или още "Запази се себе си в едно Memento и го дай да го пушнем в $savedStates"
array_push($this->savedStates, $this->originator->saveToMemento());
$this->originator->set("State 3");
$this->originator->set("State 4");
// Push a memento, или още "Направи си селфи и ми го дай да го пушна в $savedStates"
array_push($this->savedStates, $this->originator->saveToMemento());
$this->originator->set("State 5");
$this->originator->restoreFromMemento($this->savedStates[1]);
} } (new Caretaker(new Originator))->takeCare();