Паттерн "Мементо" в Java — снимки состояния и undo
Обзор — в поведенческих паттернах. Здесь — Memento на Java: сохранить снимок состояния объекта и откатиться, не открывая внутренние поля посторонним классам.
Задача паттерна
Memento фиксирует полное состояние объекта в отдельной структуре (снимок), чтобы позже восстановить его. Аналогия — Ctrl+Z в редакторе: где-то лежит копия прошлого состояния.
Три роли:
| Роль | Пример |
|---|---|
| Originator | ServerConfig — создаёт и принимает снимок |
| Memento | ConfigMemento — неизменяемые данные снимка |
| Caretaker | ConfigHistory — стек снимков, без доступа к деталям |
Пример — конфигурация сервера
import java.time.LocalDateTime;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
record ConfigMemento(Map<String, String> properties, LocalDateTime timestamp) {
ConfigMemento {
properties = Map.copyOf(properties);
}
}
class ServerConfig {
private final Map<String, String> properties = new HashMap<>();
void set(String key, String value) {
properties.put(key, value);
}
String get(String key) {
return properties.get(key);
}
ConfigMemento save() {
return new ConfigMemento(properties, LocalDateTime.now());
}
void restore(ConfigMemento memento) {
properties.clear();
properties.putAll(memento.properties());
}
}
class ConfigHistory {
private final Deque<ConfigMemento> snapshots = new ArrayDeque<>();
void backup(ServerConfig config) {
snapshots.push(config.save());
}
void undo(ServerConfig config) {
if (!snapshots.isEmpty()) {
config.restore(snapshots.pop());
}
}
}
ServerConfig config = new ServerConfig();
ConfigHistory history = new ConfigHistory();
config.set("maxThreads", "200");
history.backup(config);
config.set("maxThreads", "500");
config.set("timeout", "30s");
history.backup(config);
config.set("maxThreads", "1");
history.undo(config);
System.out.println(config.get("maxThreads")); // 500
record с компактным конструктором даёт защитную копию Map — caretaker не сможет случайно изменить снимок снаружи.
Memento и Command
| Memento | Command | |
|---|---|---|
| Хранит | Снимок состояния | Описание действия |
| Откат | restore(memento) | undo() инвертирует операцию |
| Когда лучше | Нужна точная копия всего состояния | Нужны лог, очередь, сериализация команд |
Практика Command на Java — 126, на C# — 120.
Когда применять и риски
Уместен для undo, checkpoint, черновиков, игровых сейвов.
Риск — память: частые снимки больших объектов. Ограничивайте глубину стека, храните дельты или сжимайте историю.
См. также
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). Паттерн — это повторяющийся шаблон, узор или схема. Паттерны встречаются повсюду — в природе, архитектуре, поведении людей и, конечно, в программировании. Порождающие паттерны проектирования — это группа шаблонов, направленных на решение задач, связанных с созданием объектов. Структурные паттерны — это группа шаблонов проектирования, решающих задачи организации классов и объектов таким образом, чтобы обеспечить гибкую архитектуру программного обеспечения. Поведенческие паттерны — это группа шаблонов проектирования, которые определяют способы взаимодействия объектов и распределения ответственности между ними. Архитектурные паттерны — это проверенные решения для организации структуры программного обеспечения. Интеграция систем — одна из центральных задач в современной разработке программного обеспечения. Паттерны доменного моделирования представляют собой проверенные решения для организации бизнес-логики в программных системах. Паттерн Strategy в C# — классическая реализация через интерфейс, замена на Func и Action, DI и критерии выбора без лишних абстракций. Паттерн Iterator в C# — ручной IEnumerator, генерация итератора компилятором через yield return, ленивость, LINQ и случаи, когда класс писать всё же нужно. Abstract Factory в C# и .NET — классическая схема через интерфейсы, замена через DI-контейнер, фабричный делегат и keyed services в .NET 8. Паттерн Command в C# — классическая схема, делегаты, MediatR, очередь задач, undo и критерии выбора между объектом команды и простым вызовом сервиса. Паттерн Observer в C# — event и делегаты, IObservable IObserver, слабая связанность, отписка и как не поймать утечки памяти в долгоживущих сервисах.Обзор паттернов проектирования
Порождающие паттерны
Структурные паттерны
Поведенческие паттерны
Архитектурные паттерны
Паттерны интеграции внешних систем
Паттерны проектирования доменных моделей
Стратегия в C#
Итератор в C#
Фабрика в C#
Команда в C#
Наблюдатель в C#