Wzorzec projektowy Pamiątka (ang. Momento)

Cel:

  • Umożliwienie zachowania stanu obiektu na zewnatrz w celu jego pózniejszego odtworzenia
  • Zachowanie hermetyzacji tego obiektu

Wzorzec memento pozwala na zapamietanie, przechowywanie oraz odtworzenie stanu obiektu. Potrzeba zaimplementowania takiej funkcjonalnosci pojawia sie dość często. Memento nie ma na celu zarządzania stanem ale tylko umożliwienie bezpiecznego dostepu do niego i równie bezpiecznego odtworzenia.

Struktura

Originator zapisuje i odtwarza swój stan w postaci obiektu Memento. Obiekt Caretaker przechowuje obiekty Memento, ale nie ma dostępu do ich danych

Obiektem, którego stan należy przechować, jest Originator. Posiada on metody służące do utworzenia migawki stanu (createMemento()) oraz jej odczytania w celu przywrócenia wcześniejszego stanu (setMemento()). Obiekty-migawki stanu (Memento) przechowują stan obiektu Originator w postaci niezależnych instancji obiektu. Obiekty Memento posiadają metody getState() i setState(), służące do odczytania i zapisania stanu wewnątrz niego. Zarządzaniem kolejnymi migawkami stanu zajmuje się dedykowany obiekt Caretaker. Jednak istotą wzorca nie jest sama możliwość tworzenia migawek stanu, ale zapewnienie im właściwego poziomu bezpieczeństwa. Wzorzec Memento pozwala na dostęp do stanu zapisanego w migawce wyłącznie jego właścicielowi, czyli obiektowi Originator, natomiast inne obiekty (w tym Caretaker) mogą tylko odwoływać się do całych obiektów, a metody setState() i getState() są dla nich niewidoczne.

Uczestnicy

  • Memento
    • przechowuje zapisany stan obiektu Originator
    • uniemożliwia dostęp do tego stanu obiektowi Caretaker
  • Originator
    • tworzy obiekt Memento ze swoim aktualnym stanem
    • odtwarza stan na podstawie obiektu Memento
  • Caretaker
    • przechowuje obiekty Memento
    • nie ma dostępu do ich zawartości

Szczególną rolę we wzorcu odgrywają dwie klasy: Originator, który jest twórcą i właścicielem wszystkich migawek stanu, oraz Memento, której obiekty przechowują stan Originatora. Obiekt Originator musi posiadać możliwość utworzenia obiektu Memento oraz odczytania jego zawartości w celu przywrócenia na tej podstawie poprzedniego stanu. Memento przechowuje stan obiektu Originator zapisany w dowolnym momencie; pozwala też na dostęp do niego obiektowi Originator, natomiast uniemożliwia operacje na migawce wszelkim innym obiektom. Przykładem jest obiekt Caretaker, który zarządza utworzonymi migawkami, natomiast nie ma dostępu do ich zawartości.

Konsekwencje

  • Zachowanie hermetyzacji obiektu Memento
  • Uproszczenie obiektu Originator
    • odpowiedzialność za zapis stanu przeniesiona na Memento
  • Podwójny interfejs obiektu Memento
    • wąski: dla obiektu Caretaker
    • szeroki: dla obiektu Originator
  • Potencjalny wzrost złożoności pamięciowej
    • stan może być obszerny
    • Caretaker nie zna tego rozmiaru i nie może optymalizować sposobu zarządzania nim