Хранитель (шаблон проектирования)
Хранитель (также известный как Memento, Token, Лексема) — поведенческий шаблон проектирования.
Позволяет не нарушая инкапсуляцию зафиксировать и сохранить внутреннее состояния объекта так, чтобы позднее восстановить его в этом состоянии.
Применение
Шаблон Хранитель используется, когда:
- необходимо сохранить снимок состояния объекта (или его части) для последующего восстановления
- прямой интерфейс получения состояния объекта раскрывает детали реализации и нарушает инкапсуляцию объекта
Структура
- Originator - "Создатель"
- Caretaker - "Опекун"
- Memento - "Хранитель"
Описание
Шаблон Хранитель используется двумя объектами: "Создателем" (originator) и "Опекуном" (caretaker). "Создатель" - это объект, у которого есть внутреннее состояние. Объект "Опекун" может производить некоторые действия с "Создателем", но при этом необходимо иметь возможность восстановить изменения. Для этого "Опекун" запрашивает у "Создателя" объект "Хранителя". Затем выполняет запланированное действие (или последовательность действий). Для выполнения отката "Создателя" к состоянию, которое предшествовало изменениям, "Опекун" возвращает объект "Хранителя" его "Создателю". "Хранитель" является непрозрачным (т.е. таким, который не может или не должен изменяться "Опекуном").
Примеры реализации
import java.util.*;
class Memento {
private String state; // Сюда мы будем сохранять состояние объекта
// (В данном случае состояние - это содержимое строки)
public Memento(String stateToSave) { state = stateToSave; }
public String getSavedState() { return state; }
}
/*
* Объект, состояние которого нужно сохранить
*/
class Originator {
private String state;
public void set(String state) {
System.out.println("Originator: Setting state to "+state);
this.state = state;
}
public Memento saveToMemento() {
System.out.println("Originator: Saving to Memento.");
return new Memento(state);
}
public void restoreFromMemento(Memento m) {
state = m.getSavedState();
System.out.println("Originator: State after restoring from Memento: "+state);
}
}
/*
* Опекун. Нужен чтобы хранить несколько состояний.
* По сути является объектом ArrayList<Memento> с урезанными возможностями:
*/
class Caretaker {
private ArrayList<Memento> savedStates = new ArrayList<Memento>();
public void addMemento(Memento m) { savedStates.add(m); }
public Memento getMemento(int index) { return savedStates.get(index); }
}
class MementoExample {
public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Originator originator = new Originator();
originator.set("State1");
originator.set("State2");
caretaker.addMemento( originator.saveToMemento() );
originator.set("State3");
caretaker.addMemento( originator.saveToMemento() );
originator.set("State4");
originator.restoreFromMemento( caretaker.getMemento(1) );
}
}
class Memory {
private $_data;
public function __construct($data) {
$this->_data = $data;
}
public function load () {
return $this->_data;
}
}
class Keeper {
static $_memory = array();
static function addState($state) {
Keeper::$_memory[] = new Memory($state);
}
static function getState($index) {
return Keeper::$_memory[$index]->load();
}
}
class tObj {
private $string;
public function setState($string) {
$this->string = $string;
}
public function getState() {
return $this->string;
}
public function saveState() {
Keeper::addState($this->string);
}
public function loadState($index) {
return Keeper::getState($index);
}
}
$t = new tObj;
$t->setState("state 1");
$t->setState("state 2");
$t->saveState();
$t->setState("state 3");
$t->saveState();
$t->setState("state 4");
print $t->getState(); // state 4
print $t->loadState(1); //state 3