Паттерны GoF - Memento (лекция)
Автор: Rageous
<MiF> Memento
<MiF> Назначение - не нарушая инкапсуляции позволяет фиксировать и вынести за пределы объекта его внутреннее состояние, чтобы потом можно было восстановит объект
<MiF> применять когда:
<MiF> 1. необходимо сохранить состояние объекта либо его части, чтобы потом объект можно было восстановить в этом же состоянии
<MiF> 2. прямое получение этого состояния нарушает инкапсуляцию
<MiF> Участники:
<MiF> 1. Memento - хранитель. Сохраняет внутренее состояние объекта Originator.
<MiF> Также он запрещает доступ к себе для всех, кроме хозяина
<MiF> 2. Originator - хозяин, создает хранителя. Использует его для восстановления состояния
<MiF> 3. Caretaker - посыльный, отвечает за сохранения хранителя, не знает его внутренее содержимое
<MiF> Результаты:
<MiF> 1. Позволяет избежать открытия информации, которую должен знать только хозяин, но которую нужно хранить вне него. Короче сохраняет инкапсуляцию
<MiF> 2. Можно сделать то же самое без всяких хранителей, но тогда придется усложнить структуру хозяина, и добавить в него функциональность для сохранения состояния
<MiF> Но при этом структура хозяина усложнится
<MiF> Короче паттерн хранитель позволяет упростить структуру хозяина
<MiF> Минусы понятны - хранители могут быть жирными и избыточными и кидать каждый раз в них данные будет медленно
<Padawan> Как переводится Memento ?
<MiF> хранитель
<Rageous> мне второй результат не очень понятен
<Rageous> что значит "сделать без хранителей"?
<MiF> Ну сам объект может хранить свои состояния и рулить их восстановлением
<MiF> только для этого всю реализацию придется запихать в него
<MiF> А так мы выносим это дело наружу
<MiF> при этом не нарушая инкапсуляции
<Rageous> хм... а кто сохраняет данные в хранителя? разве не сам объект?
<Rageous> вопрос про применение хранетиля в геймдеве уже задали?
<MiF> я пример кода ушел писать
<Rageous> ок
<MiF> сам не применял :)
<MiF> а ты?
<new_> я применял
<Rageous> расскажи )
<Rageous> мне в геймдеве не довелось
<new_> для осуществления загрузки/сохранения
<Rageous> а чем он там поможет?
<new_> только там Caretaker'ом был std::iostream
<MiF> короче Memento - отделение менеджемента состояний от самого объекта
<Rageous> насколько я могу прикинуть, можно заюзать его в квик сейва: в отличие от обычного его нужно грузить быстро, а полная сериализация на диск и десериализация идут медленно. тогда можно оставить "слепок" уровня в хранителе, а его в памяти - тогда быстрая загрузка будет идти значительно быстрее
<MiF> Rageous, отличная идея
<Rageous> еще, как вариант, пошаговые игры с кнопкой "переиграть ход"
<MiF> Ну для откатов он часто используется
<Rageous> потом: да, инвентарь - что-то поперекладывали, не понравилось, все вернули
<Rageous> по кнопке "отмена"
<new_> я так и делал, просто менял ofstream на streangstream
<MiF> Ладно, пойду напишу абстрактный пример
<MiF> может понятнее станет
<Rageous> угу, ждем )
<Rageous> тож интересный вариант: перед началом игры конфигурим перца, а сохраненные пользователем конфигурации сохраняем в мементо. позже эти хранители можно скинуть на диск или дать пользователю выбрать один из созданных им и т.п. - т.к. хранитель может малой кровью описать целого перса, то хранение нескольких (и даже множества) в памяти вряд ли станет серьезной проблемой. единственное, конечно - восстановление состояния по хранителю тем медленнее, чем меньше хранитель занимает, потому придется некоторое время побаловаться балансом "скорость восстановления - вес хранителя" :)
<MiF> http://www.everfall.com/paste/id.php?c4w9r836nv8a
<MiF> вообщем смысл паттерна - вынос менджмента состояний объекта из самого объекта, при сохранении инкапсуляции
<MiF> *менеджмента
<Rageous> угу
<MiF> вопросы есть?
<Rageous> а Caretaker обязательная часть паттерна разве?
<MiF> получается, что так
<Rageous> мм... дай подумать
<MiF> если хранить мементо в самом объекте - то смысла никакого нет
<Rageous> почему я просто не могу получить хранителя от объекта в произвольном месте/класс?
<Rageous> *классе
<Rageous> Caretaker получается менеджером состояний, да, но кто мне мешает вообще обойтись без этого менеджмента, получения состояния по метке и т.п.?
<Rageous> блин, да че за....
<Rageous> в общем, почему я просто не могу получить хранителя от объекта в произвольном месте/класс?
<Rageous> [01:20:30] <Rageous> *классе
<Rageous> [01:21:47] <Rageous> Caretaker получается менеджером состояний, да, но кто мне мешает вообще обойтись без этого менеджмента, получения состояния по метке и т.п.?
<new_> в своём объекте что надо хранить?
<new_> или от чего наследовать?
<MiF> это скорее уже не мементо будет
<Rageous> в общем, caretaker мне лично каким-то надуманным кажется
<MiF> если нужно вынести хранителя за пределы объекта - то да, это Memento
<MiF> в роли кейртейкера может выступать что угодно
<MiF> что получает и хранит хранителей
<Rageous> любой получатель хранителей, да
<MiF> все, все согласны :)
<Rageous> :)
<MiF> new_ что не ясно?
<MiF> как тебе использовать мементо?
<new_> всё, всё понял :)
<MiF> ок, поехали дальше
22 января 2006