Pamiątka (ang. Memento) to wzorzec z grupy wzorców behawioralnych. Jego głównym zadaniem jest zapisywanie i odczytywanie stanu obiektu. Korzystamy z niego gdy nie chcemy dać użytkownikowi w głównym obiekcie możliwości manipulacji polami czy metodami.
Za przykład może posłużyć aplikacja do edycji tekstu, w której chcemy aby użytkownik miał możliwość cofnięcia się do poprzedniego zapisanego stanu. Tworzymy więc klasę główną będącą naszym orignatorem – „TextEditorApp”. Klasa ta posiada pola prywatne określające na przykład wprowadzony tekst, aktualną czcionkę i styl. Posiada także metody publiczne, dostępne dla użytkownika: do dodawania nowego tekstu/operacji, do zapisywania stanu dokumentu i do ładowania zapisanego stanu. Następnie stwórzmy klasę memento – „TextEditorAppMemento”, która będzie posiadała prywatne pola, konstruktor i gettery dla pól o domyślnym dostępie. Kolejnym krokiem jest stworzenie caretakera – „TextEditorAppCaretaker”, który zawiera prywatną listę obiektów typu TextEditorAppMemento oraz dwie metody publiczne – do dodawania pamiątek, która zapisuje aktualną wersję pliku oraz metoda do pobierania pamiątek, która zwraca ostatnio zapisaną pamiątkę, a więc obiekt TextEditorAppMemento.
TextEditorApp.java
package memento.example.textEditorApp;
public class TextEditorApp {
private String text;
private String currentFont;
private String styles;
public void addOperation(String text, String currentFont, String styles) {
this.text = text;
this.currentFont = currentFont;
this.styles = styles;
System.out.println("Dodano nową operację.");
}
public TextEditorAppMemento save() {
return new TextEditorAppMemento(this.text,this.currentFont, this.styles);
}
public void load(TextEditorAppMemento textEditorAppMemento) {
this.text = textEditorAppMemento.getText();
this.currentFont = textEditorAppMemento.getCurrentFont();
this.styles = textEditorAppMemento.getStyles();
}
}
TextEditorAppMemento.java
package memento.example.textEditorApp;
class TextEditorAppMemento {
private String text;
private String currentFont;
private String styles;
TextEditorAppMemento(String text, String currentFont, String styles) {
this.text = text;
this.currentFont = currentFont;
this.styles = styles;
}
String getText() {
return text;
}
String getCurrentFont() {
return currentFont;
}
String getStyles() {
return styles;
}
}
TextEditorAppCaretaker.java
package memento.example.textEditorApp;
import java.util.ArrayList;
import java.util.List;
public class TextEditorAppCaretaker {
List<TextEditorAppMemento> mementos = new ArrayList<TextEditorAppMemento>();
public void addMemento(TextEditorAppMemento textEditorAppMemento) {
mementos.add(textEditorAppMemento);
System.out.println("Zapisano wersję pliku");
}
public TextEditorAppMemento getMemento() {
int index = mementos.size() - 1;
System.out.println("Cofnięto operacje do ostatniego zapisu, tekst: " + mementos.get(index).getText());
return mementos.get(index);
}
}
Main.java
package memento.example;
import memento.example.textEditorApp.TextEditorApp;
import memento.example.textEditorApp.TextEditorAppCaretaker;
public class Main {
public static void main(String[] args) {
TextEditorAppCaretaker textEditorAppCaretaker = new TextEditorAppCaretaker();
TextEditorApp textEditorApp = new TextEditorApp();
textEditorApp.addOperation("Strona", "tahoma", "nagłówek 1");
textEditorApp.addOperation("Strona domowa", "tahoma", "nagłówek 1");
textEditorAppCaretaker.addMemento(textEditorApp.save());
textEditorApp.addOperation("Strona domowa bloga", "tahoma", "nagłowek 1");
textEditorApp.addOperation("Strona domowa bloga programistycznego", "tahoma", "nagłówek 1");
textEditorApp.load(textEditorAppCaretaker.getMemento());
}
}
PODSUMOWANIE
Wzorzec pamiątka – memento jest wykorzystywany kiedy, jak już wyżej wspomniano, musimy zapamiętać jeden lub więcej stanów danego obiektu. Wówczas wydzielamy stan obiektu do osobnej klasy – memento, a sterowanie procesem zapisu i odczytu powierzamy klasie trzeciej – caretakerowi. Zaletą wzorca jest enkapsulacja poszczególnych stanów obiektu – nikt poza originatorem nie ma bezpośredniego dostępu do pamiątek, caretaker zaś przechowuje kolekcję pamiątek, ale nie może modyfikować żadnej z nich. Wzorzec ma wiele zastosowań, jednym z nich są formularze wielokrokowe, kiedy chcemy dać użytkownikowi możliwość cofnięcia się do poprzednich kroków.