Хранитель (шаблон проектирования): различия между версиями

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
[непроверенная версия][непроверенная версия]
Содержимое удалено Содержимое добавлено
 
(не показано 8 промежуточных версий 6 участников)
Строка 26: Строка 26:
[[Файл:Memento design pattern.png|center|frame|[[UML]] диаграмма, описывающая классический вариант шаблона Хранитель]]
[[Файл:Memento design pattern.png|center|frame|[[UML]] диаграмма, описывающая классический вариант шаблона Хранитель]]


Нестандартный вариант:
Не верьте рукожопам, не знающим UML!
[[Файл:UML диаграмма, описывающая нестандартный вариант шаблона Хранитель.png|center|frame|[[UML]] диаграмма, описывающая нестандартный вариант шаблона Хранитель]]
[[Файл:UML диаграмма, описывающая нестандартный вариант шаблона Хранитель.png|center|frame|[[UML]] диаграмма, описывающая нестандартный вариант шаблона Хранитель]]


Строка 41: Строка 41:


== Примеры реализации ==
== Примеры реализации ==

=== Стандартный вариант шаблона на Python ===
{{Hider_hiding
| title = Исходный текст на языке [[Python]]
| content =
<source lang="python">

class Memento:
def __init__(self, state: str):
self.__state = state

def get_state(self) -> str:
return self.__state


class Caretaker:
def __init__(self, memento: Memento):
self.__memento = memento

def get_memento(self) -> Memento:
return self.__memento


class Originator:
def __init__(self, state: str):
self.__state = state

@property
def state(self) -> str:
return self.__state

@state.setter
def state(self, state: str) -> None:
self.__state = state

def save_state(self) -> Memento:
return Memento(self.__state)

def restore_state(self, memento: Memento) -> None:
self.__state = memento.get_state()


if __name__ == '__main__':
originator = Originator(state='on')
print(originator.state)

caretaker = Caretaker(originator.save_state())

originator.state = 'off'
print(originator.state)

originator.restore_state(caretaker.get_memento())
print(originator.state)


# on
# off
# on
</source>
}}


=== Стандартный вариант шаблона на Java ===
=== Стандартный вариант шаблона на Java ===
Строка 125: Строка 185:
<?php
<?php


/*
/**
* Паттерн хранитель, используется для хранения и восстановления состояния объекта
* Паттерн «Хранитель» хранит и восстанавливает состояния объекта
*/
*/
namespace Memento {
namespace Memento {


/**
/**
* Создатель сохраняет и восстанавливает внутреннее состояние
* Класс поддерживаюший сохранение состояний внутреннего состояния
*/
*/
class Originator {
class Originator {
Строка 150: Строка 210:
* @return Memento
* @return Memento
*/
*/
public function CreateMemento() {
public function saveMemento() {
return new Memento($this->state);
return new Memento($this->state);
}
}
Строка 158: Строка 218:
* @param \Memento\Memento $memento
* @param \Memento\Memento $memento
*/
*/
public function setMemento(Memento $memento) {
public function restoreMemento(Memento $memento) {
echo sprintf("Restoring state...\n");
echo sprintf("Restoring state...\n");
$this->state = $memento->getState();
$this->state = $memento->getState();
Строка 166: Строка 226:


/**
/**
* Хранитель состояния
* Снимок состояния
*/
*/
class Memento {
class Memento {
Строка 183: Строка 243:


/**
/**
* Смотрящий за состоянием объекта
* Смотрящий (опекун) за состоянием объекта
*/
*/
class Caretaker {
class Caretaker {
Строка 199: Строка 259:
}
}



$originator = new Originator();
$originator = new Originator();
$originator->setState("On");
$originator->setState("On");
Строка 205: Строка 265:
// Store internal state
// Store internal state
$caretaker = new Caretaker();
$caretaker = new Caretaker();
$caretaker->setMemento($originator->CreateMemento());
$caretaker->setMemento($originator->saveMemento());


// Continue changing originator
// Continue changing originator
Строка 211: Строка 271:


// Restore saved state
// Restore saved state
$originator->setMemento($caretaker->getMemento());
$originator->restoreMemento($caretaker->getMemento());
}
}
Строка 370: Строка 430:
}
}


public class Foo
public class Foo : IOriginator
: IOriginator
{
{
public string StringProperty
public string StringProperty
Строка 393: Строка 452:
public void Print()
public void Print()
{
{
Console.WriteLine("=============");
Console.WriteLine("=============");
Console.WriteLine("StringProperty value: {0}",StringProperty);
Console.WriteLine("StringProperty value: {0}",StringProperty);
Console.WriteLine("IntProperty value: {0}",IntProperty);
Console.WriteLine("IntProperty value: {0}",IntProperty);
Console.WriteLine("=============");
Console.WriteLine("=============");
}
}

object IOriginator.GetMemento()
object IOriginator.GetMemento()
{
{
return new Memento { StringProperty = this.StringProperty, IntProperty = this.IntProperty };
return new Memento { StringProperty = this.StringProperty, IntProperty = this.IntProperty };

}
}

void IOriginator.SetMemento(object memento)
void IOriginator.SetMemento(object memento)
{
{
Строка 669: Строка 728:
=== Нестандартный вариант шаблона на C++ ===
=== Нестандартный вариант шаблона на C++ ===
{{Hider_hiding
{{Hider_hiding
| title = Исходный текст на языке [[С++]]
| title = Исходный текст на языке [[C++]]
| content =
| content =
<source lang="cpp">
<source lang="cpp">
Строка 756: Строка 815:


== Ссылки ==
== Ссылки ==
* [http://cpp-reference.ru/patterns/behavioral-patterns/memento/ Паттерн Memento (хранитель)] — назначение, описание, особенности и реализация на С++.
* [http://cpp-reference.ru/patterns/behavioral-patterns/memento/ Паттерн Memento (хранитель)] — назначение, описание, особенности и реализация на C++.
{{Типы шаблонов проектирования}}
{{Типы шаблонов проектирования}}
[[Категория:Шаблоны проектирования]]
[[Категория:Шаблоны проектирования]]

Текущая версия от 05:16, 6 ноября 2024

Хранитель
Memento
Тип поведенческий
Описан в Design Patterns Да

Хранитель (англ. Memento) — поведенческий шаблон проектирования, позволяющий, не нарушая инкапсуляцию, зафиксировать и сохранить внутреннее состояние объекта так, чтобы позднее восстановить его в это состояние.

Существует два возможных варианта реализации данного шаблона: классический, описанный в книге Design Patterns, и реже встречающийся нестандартный вариант.

Применение

[править | править код]

Шаблон Хранитель используется, когда:

  • необходимо сохранить снимок состояния объекта (или его части) для последующего восстановления
  • прямой интерфейс получения состояния объекта раскрывает детали реализации и нарушает инкапсуляцию объекта

Классический вариант:

UML диаграмма, описывающая классический вариант шаблона Хранитель

Нестандартный вариант:

UML диаграмма, описывающая нестандартный вариант шаблона Хранитель
  • Originator — «Создатель»
  • Caretaker — «Опекун»
  • Memento — «Хранитель»

Классический вариант: Шаблон Хранитель используется двумя объектами: «Создателем» (originator) и «Опекуном» (caretaker). «Создатель» — это объект, у которого есть внутреннее состояние. Объект «Опекун» может производить некоторые действия с «Создателем», но при этом необходимо иметь возможность откатить изменения. Для этого «Опекун» запрашивает у «Создателя» объект «Хранителя». Затем выполняет запланированное действие (или последовательность действий). Для выполнения отката «Создателя» к состоянию, которое предшествовало изменениям, «Опекун» возвращает объект «Хранителя» его «Создателю». «Хранитель» является непрозрачным (то есть таким, который не может или не должен изменяться «Опекуном»).

Нестандартный вариант: Отличие данного варианта от классического заключено в более жёстком ограничении на доступ «Опекуна» к внутреннему состоянию «Создателя». В классическом варианте у «Опекуна» есть потенциальная возможность получить доступ к внутренним данным «Создателя» через «Хранителя», изменить состояние и установить его обратно «Создателю». В данном варианте «Опекун» обладает возможностью лишь восстановить состояние «Хранителя», вызвав Restore. Кроме всего прочего, «Опекуну» не требуется владеть связью на «Хранителя», чтобы восстановить его состояние. Это позволяет сохранять и восстанавливать состояние сложных иерархических или сетевых структур (состояния объектов и всех связей между ними) путём сбора снимков всех зарегистрированных объектов системы.

Примеры реализации

[править | править код]

Стандартный вариант шаблона на Python

[править | править код]

Стандартный вариант шаблона на Java

[править | править код]

Стандартный вариант шаблона на PHP5

[править | править код]

Первый вариант шаблона С#

[править | править код]


Нестандартный вариант шаблона

[править | править код]

Нестандартный вариант шаблона на C++

[править | править код]