Содержание
- 2. Содержание Команда Пример реализации Команды Снимок Пример реализации снимка
- 3. Проблема Некоторые операции, например «сохранить», можно вызывать из нескольких мест — нажав кнопку на панели управления,
- 4. Решение Программы обычно структурированы в виде слоёв. Самый распространённый пример — слои интерфейса и бизнес-логики. Первый
- 5. Вариант решения Параметры, с которыми должен быть вызван метод объекта получателя, можно загодя сохранить в полях
- 6. Структура Отправитель хранит ссылку на объект команды и обращается к нему, когда нужно выполнить какое-то действие.
- 7. Схема
- 8. Паттерн Команда служит для ведения истории выполненных операций, позволяя, отменять их, если потребуется Команды, которые меняют
- 9. Пример реализации отмены в текстовом редакторе
- 10. Код класса Command // Абстрактная команда задаёт общий интерфейс для всех команд. abstract class Command is
- 11. Команды // Конкретные команды. class CopyCommand extends EditorCommand is // Команда копирования не записывается в историю,
- 12. Класс Редактор // Класс редактора содержит непосредственные операции над текстом. Он отыгрывает // роль получателя –
- 13. Класс приложения // Код, привязывающий команды к элементам интефрейса может выглядеть // примерно так. method createUI()
- 14. Применимость Когда вы хотите параметризовать объекты выполняемым действием. Команда превращает операции в объекты. А объекты можно
- 15. Шаги реализации Создайте общий интерфейс команд и определите в нём метод запуска. Один за другим создайте
- 16. Преимущества и недостатки Убирает прямую зависимость между объектами, вызывающими операции и объектами, которые их непосредственно выполняют.(+)
- 17. Отношения с другими паттернами Обработчики в Цепочке обязанностей могут быть выполнены в виде Команд. В этом
- 18. Снимок Проблема Предположим, что вы пишете текстовый редактор. Помимо обычного редактирования, ваш редактор позволяет менять форматирование
- 19. Решение Все проблемы, описанные выше, возникают из-за нарушения инкапсуляции. Это когда одни объекты пытаются сделать работу
- 20. Структура Классическая реализация на вложенных классах Классическая реализация паттерна полагается на механизм вложенных классов, которые доступны
- 21. Классическая реализация на вложенных классах Классическая реализация паттерна полагается на механизм вложенных классов, которые доступны только
- 22. Реализация с промежуточным пустым интерфейсом Подходит для языков, не имеющих механизма вложенных классов (PHP). В этой
- 23. Снимки с повышенной защитой Когда нужно полностью исключить доступ к состоянию Создателей и Снимков. Реализация разрешает
- 24. Пример В этом примере паттерн Снимок используется совместно с паттерном Команда и позволяет хранить резервные копии
- 25. Класс Редактор // Класс создателя должен иметь специальный метод, который сохраняет состояние // создателя в новом
- 26. Состояние редактора // Снимок хранит прошлое состояние редактора. class EditorState is private field editor: Editor private
- 27. Опекун // Опекуном может выступать класс команд (см. паттерн Команда). В этом случае, // команда сохраняет
- 28. Применимость Когда вам нужно сохранять мгновенный снимок состояния объекта (или его части), чтобы впоследствии объект можно
- 29. Шаги реализации Определите класс создателя, объекты которого должны создавать снимки своего состояния. Создайте класс снимка и
- 30. Преимущества и недостатки Не нарушает инкапсуляции исходного объекта.(+) Упрощает структуру исходного объекта. Ему не нужно хранить
- 31. Отношения с другими паттернами Команду и Снимок можно использовать сообща для реализации отмены операций. В этом
- 33. Скачать презентацию
Слайд 2Содержание
Команда
Пример реализации Команды
Снимок
Пример реализации снимка
Содержание
Команда
Пример реализации Команды
Снимок
Пример реализации снимка
Слайд 3Проблема
Некоторые операции, например «сохранить», можно вызывать из нескольких мест — нажав кнопку
Проблема
Некоторые операции, например «сохранить», можно вызывать из нескольких мест — нажав кнопку
Слайд 4Решение
Программы обычно структурированы в виде слоёв. Самый распространённый пример — слои интерфейса и
Решение
Программы обычно структурированы в виде слоёв. Самый распространённый пример — слои интерфейса и
Первый всего лишь рисует красивую картинку для пользователя.
Но когда нужно сделать что-то важное, интерфейс «просит» слой бизнес-логики заняться этим.
В реальности это выглядит так: один из объектов интерфейса напрямую вызывает метод одного из объектов бизнес-логики, передавая в него какие-то параметры.
Паттерн Команда предлагает не отправлять такие вызовы напрямую, а «завернуть» их в отдельные объекты с единственным методом, который приводит вызов в действие.
Слайд 5Вариант решения
Параметры, с которыми должен быть вызван метод объекта получателя, можно загодя
Вариант решения
Параметры, с которыми должен быть вызван метод объекта получателя, можно загодя
Классы команд можно объединить под общим интерфейсом, c единственным методом запуска команды. После этого одни и те же отправители смогут работать с различными командами, не привязываясь к их классам. Даже больше, команды можно будет взаимозаменять на лету, изменяя итоговое поведение отправителей.
Слайд 6Структура
Отправитель хранит ссылку на объект команды и обращается к нему, когда нужно выполнить
Структура
Отправитель хранит ссылку на объект команды и обращается к нему, когда нужно выполнить
Команда описывает общий для всех конкретных команд интерфейс. Обычно, здесь описан всего один метод для запуска команды.
Конкретные команды реализуют различные запросы, следуя общему интерфейсу команд. Обычно, команда не делает всю работу самостоятельно, а лишь передаёт вызов получателю — определённому объекту бизнес-логики.
Параметры, с которыми команда обращается к получателю, следует хранить в виде полей. В большинстве случаев, объекты команд можно сделать неизменяемым, предавая в них все необходимые параметры только через конструктор.
Получатель содержит бизнес-логику программы. В этой роли может выступать практически любой объект. Обычно, команды перенаправляют вызовы получателям. Но иногда, чтобы упростить программу, вы можете избавиться от получателей, слив их код в классы команд.
Слайд 7Схема
Схема
Слайд 8Паттерн Команда служит для ведения истории выполненных операций, позволяя, отменять их, если потребуется
Команды, которые
Паттерн Команда служит для ведения истории выполненных операций, позволяя, отменять их, если потребуется
Команды, которые
Копии выполненных команд помещаются в историю команд, откуда они могут быть доставлены, если нужно будет сделать отмену операции.
Классы элементов интерфейса, истории команд и прочие не зависят от конкретных классов команд, так как работают с ними через общий интерфейс.
Это позволяет добавлять в приложение новые команды, не изменяя существующий код.
Слайд 9Пример реализации отмены в текстовом редакторе
Пример реализации отмены в текстовом редакторе
Слайд 10Код класса Command
// Абстрактная команда задаёт общий интерфейс для всех команд.
abstract
Код класса Command
// Абстрактная команда задаёт общий интерфейс для всех команд.
abstract
protected field app: Application
protected field editor: Editor
protected field backup: text
constructor Command(app: Application, editor: Editor) is
this.app = app this.editor = editor
// Сохраняем состояние редактора.
method saveBackup() is
backup = editor.text
// Восстанавливаем состояние редактора.
method undo() is editor.text = backup
// Главный метод команды остаётся абстрактным, чтобы каждая конкретная
// команда определила его по-своему. Метод должен возвратить true или false,
// в зависимости о того, изменила ли команда состояние редактора, а значит,
// нужно ли её сохранить в истории.
abstract method execute()
Слайд 11Команды
// Конкретные команды.
class CopyCommand extends EditorCommand is
// Команда копирования не
Команды
// Конкретные команды.
class CopyCommand extends EditorCommand is
// Команда копирования не
// состояние редактора.
method execute() is
app.clipboard = editor.getSelection() return false
class CutCommand extends EditorCommand is // Команды, меняющие состояние редактора, сохраняют состояние редактора
// перед своим действием и сигнализируют об изменении, возвращая true.
method execute() is
saveBackup()
app.clipboard = editor.getSelection()
editor.deleteSelection() return true
class PasteCommand implements Command is
method execute() is
saveBackup()
editor.replaceSelection(app.clipboard) return true // Отмена это тоже команда.
class UndoCommand implements Command is
method execute() is
app.undo()
return false // Глобальная история команд — это стек.
class CommandHistory is
private field history: array of Command // Последний зашедший...
method push(c: Command) is
Push command to the end of history array. // ...выходит первым.
method pop():Command is Get the most recent command from history.
Слайд 12Класс Редактор
// Класс редактора содержит непосредственные операции над текстом. Он отыгрывает
//
Класс Редактор
// Класс редактора содержит непосредственные операции над текстом. Он отыгрывает
//
class Editor is
field text: string
method getSelection() is
Return selected text.
method deleteSelection() is
Delete selected text.
method replaceSelection(text) is
Insert clipboard contents at current position.
// Класс приложения настраивает объекты для совместной работы. Он выступает в
// роли отправителя — создаёт команды, чтобы выполнить какие-то действия.
class Application is
field clipboard: string
field editors: array of Editors
field activeEditor: Editor
field history: CommandHistory
Слайд 13Класс приложения
// Код, привязывающий команды к элементам интефрейса может выглядеть
// примерно
Класс приложения
// Код, привязывающий команды к элементам интефрейса может выглядеть
// примерно
method createUI() is // ...
copy = function() { executeCommand(new CopyCommand(this, activeEditor)) }
copyButton.setCommand(copy)
shortcuts.onKeyPress("Ctrl+C", copy)
cut = function() { executeCommand(new CutCommand(this, activeEditor)) } cutButton.setCommand(cut)
shortcuts.onKeyPress("Ctrl+X", cut)
paste = function() { executeCommand(new PasteCommand(this, activeEditor)) }
pasteButton.setCommand(paste) shortcuts.onKeyPress("Ctrl+V", paste)
undo = function() { executeCommand(new UndoCommand(this, activeEditor)) }
undoButton.setCommand(undo)
shortcuts.onKeyPress("Ctrl+Z", undo) // Запускаем команду и проверяем, надо ли добавить её в историю.
method executeCommand(command) is
if (command.execute) history.push(command) // Берём последнюю команду из истории и заставляем её все отменить. Мы не
// знаем конкретный тип команды, но это и не важно, так как каждая команда
// знает как отменить своё действие.
method undo() is
command = history.pop() if (command != null) command.undo()
Слайд 14Применимость
Когда вы хотите параметризовать объекты выполняемым действием.
Команда превращает операции в объекты. А
Применимость
Когда вы хотите параметризовать объекты выполняемым действием.
Команда превращает операции в объекты. А
Для библиотеки графического меню и нужно, чтобы пользователи могли использовать меню в разных приложениях, не меняя каждый раз код ваших классы. Применив паттерн, пользователям не придётся изменять классы меню, вместо этого они будут конфигурировать объекты меню различными командами.
Когда вы хотите ставить операции в очередь, выполнять их по расписанию или передавать по сети.
Как и любые другие объекты, команды можно сериализовать, то есть превратить в строку, чтобы потом сохранить в файл или базу данных. Затем, в любой удобный момент, её можно достать обратно, снова превратить в объект команды, и выполнить. Таким же образом команды можно передавать по сети, логировать или выполнять на удалённом сервере.
Когда вам нужна операция отмены.
Главная вещь, которая вам нужна, чтобы иметь возможность отмены операций — это хранение истории. Среди многих способов как это делается, паттерн Команда является, пожалуй, самым популярным.
После выполнения операции, копия команды попадает в стек истории, все ещё неся в себе сохранённое состояние объекта. Если потребуется отмена, программа возьмёт последнюю команду из истории и возобновит сохранённое в ней состояние.
Этот способ имеет две особенности. Во-первых, точное состояние объектов не так-то просто сохранить, ведь часть его может быть приватным. Но с этим может помочь справиться паттерн Снимок.
Во-вторых, копии состояния могут занимать довольно много оперативной памяти
Слайд 15Шаги реализации
Создайте общий интерфейс команд и определите в нём метод запуска.
Один за
Шаги реализации
Создайте общий интерфейс команд и определите в нём метод запуска.
Один за
Кроме этого, команда должна иметь поля для хранения параметров, которые нужны при вызове методов получателя. Значения всех этих полей команда должна получать через конструктор.
И наконец, реализуйте основной метод команды, вызывая в нём те или иные методы получателя.
Добавьте в классы отправителей поля для хранения команд. Объект-отправитель должен принимать готовый объект команды извне через конструктор, либо через сеттер команды.
Измените основной код отправителей так, чтобы они делегировали выполнение действия команде.
Порядок инициализации объектов должен выглядеть так:
Создаём объекты получателей.
Создаём объекты команд, связав их с получателями.
Создаём объекты отправителей, связав их с командами.
Слайд 16Преимущества и недостатки
Убирает прямую зависимость между объектами, вызывающими операции и объектами, которые
Преимущества и недостатки
Убирает прямую зависимость между объектами, вызывающими операции и объектами, которые
Позволяет реализовать простую отмену и повтор операций.(+)
Позволяет реализовать отложенный запуск команд.(+)
Позволяет собирать сложные команды из простых.(+)
Соблюдает принцип открытости/закрытости.(+)
Усложняет код программы за счёт дополнительных классов.(-)
Слайд 17Отношения с другими паттернами
Обработчики в Цепочке обязанностей могут быть выполнены в виде Команд.
В этом
Отношения с другими паттернами
Обработчики в Цепочке обязанностей могут быть выполнены в виде Команд.
В этом
Но есть и другой подход, в котором сам запрос является Командой, посланной по цепочке объектов. В этом случае одна и та же операция может быть выполнена над множеством разных контекстов, представленных в виде цепочки.
Команду и Снимок можно использовать сообща для реализации отмены операций. В этом случае объекты команд будут отображать выполненные действие над объектом, снимки — хранить копию состояния этого объекта до того, как команда была выполнена.
Команда и Стратегия похожи по духу, но отличаются масштабом и применением:
Команду используют, чтобы превратить любые разнородные действия в объекты. Параметры операции превращаются в поля объекта. Этот объект теперь можно логировать, хранить в истории для отмены, передавать во внешние сервисы и так далее.
С другой стороны, Стратегия описывает разные способы сделать одно и то же действие, позволяя взаимозаменять эти способы в каком-то объекте контекста.
Если Команду нужно копировать перед вставкой в историю выполненных команд, вам может помочь Прототип.
Посетитель это более мощный аналог Команды, которую можно выполнить сразу над объектами нескольких классов.
Слайд 18Снимок
Проблема
Предположим, что вы пишете текстовый редактор. Помимо обычного редактирования, ваш редактор позволяет
Снимок
Проблема
Предположим, что вы пишете текстовый редактор. Помимо обычного редактирования, ваш редактор позволяет
В какой-то момент вы решили сделать все эти действия отменяемыми. Для этого вам нужно сохранять текущее состояние редактора перед тем, как выполнить любое действие..
Чтобы сделать копию состояния объекта, достаточно скопировать значение его полей.
Если вы решите провести рефакторинг — убрать или добавить парочку полей в класс редактора — то придётся изменять код всех классов, которые могли копировать состояние редактора.
Чтобы сделать копию состояния, вам нужно записать значения всех этих полей в некий «контейнер».
Скорее всего, вам понадобится хранить массу таких «контейнеров», поэтому удобней всего сделать их объектами одного класса.
Этот класс должен иметь массу полей и практически никаких методов. Чтобы другие классы смогли записывать и читать из него данные, вам придётся сделать его поля публичными.
Другие классы станут зависимыми от любых изменений в классе редактора.
Получается, нам придётся либо открывать классы для всех желающих, испытывая массу хлопот с поддержкой кода, либо делать классы закрытыми, но отказаться от идеи отмены операций.
Слайд 19Решение
Все проблемы, описанные выше, возникают из-за нарушения инкапсуляции. Это когда одни объекты
Решение
Все проблемы, описанные выше, возникают из-за нарушения инкапсуляции. Это когда одни объекты
Паттерн Снимок поручает создание копии состояния объекта самому объекту, который этим состоянием владеет. Вместо того чтобы делать снимок «извне», наш редактор сам сделает копию своих полей — ведь ему доступны все поля, даже приватные.
Паттерн предлагает держать копию состояния в специальном объекте «снимке» с ограниченным интерфейсом, позволяющим, например, узнать дату изготовления или название снимка. Но с другой стороны, снимок должен быть открыт для своего «создателя», позволяя прочесть и восстановить его внутреннее состояние.
Эта схема позволяет создателям производить снимки и отдавать их для хранения другим объектам, называемым «опекунами».
Опекунам будет доступен только ограниченный интерфейс снимка, поэтому они никак не смогут повлиять на внутренности самого снимка. В нужный момент, опекун может попросить создателя восстановить своё состояние, передав в него соответствующий снимок.
В нашем примере с редактором, опекуном можно сделать отдельный класс, который будет хранить список выполненных операций.
Если пользователь решит откатить операцию, класс истории возьмёт последний снимок из стека и отправит его в редактор для восстановления.
Слайд 20Структура
Классическая реализация на вложенных классах
Классическая реализация паттерна полагается на механизм вложенных классов,
Структура
Классическая реализация на вложенных классах
Классическая реализация паттерна полагается на механизм вложенных классов,
Создатель делает снимки своего состояния по запросу, а также воспроизводит прошлое состояние, если подать в него готовый снимок.
Снимок — это простой объект данных, содержащий состояние создателя. Надёжней всего сделать объекты снимков неизменяемыми и передавать в них состояние только через конструктор.
Опекун должен знать, когда и зачем делать снимок создателя, а также когда его нужно восстанавливать.
Опекун может хранить историю прошлых состояний создателя в виде стека из снимков. Если понадобится сделать отмену, он возьмёт последний снимок и передаст его создателю для восстановления.
В этой реализации снимок — это внутренний класс по отношению к классу создателя, поэтому тот имеет полный доступ к его полям и методам, несмотря на то, что они объявлены приватными. Опекун же не имеет доступа ни к состоянию, ни к методам снимков и может всего лишь хранить ссылки на эти объекты.
Реализация с промежуточным пустым интерфейсом
Подходит для языков, не имеющих механизма вложенных классов (PHP).
В этой реализации создатель работает напрямую с конкретным классом снимка, а опекун — только с его ограниченным интерфейсом.
Благодаря этому достигается тот же эффект, что и в классической реализации. Создатель имеет полный доступ к снимку, а опекун — нет.
Снимки с повышенной защитой
Когда нужно полностью исключить доступ к состоянию Создателей и Снимков.
Реализация разрешает иметь несколько видов создателей и снимков. Каждому классу создателей соответствует собственный класс снимков. Ни создатели, ни снимки не позволяют прочесть их состояние.
Здесь опекун ещё более жёстко ограничен в доступе к состоянию создателей и снимков. Но с другой стороны, опекун становится независим от создателей, так как метод восстановления теперь находится в самих снимках.
Снимки теперь связаны с теми создателями, из которых они сделаны. Они по-прежнему получают состояние через конструктор. Благодаря близкой связи между классами, снимки знают, как восстановить состояние своих создателей.
Слайд 21Классическая реализация на вложенных классах
Классическая реализация паттерна полагается на механизм вложенных классов,
Классическая реализация на вложенных классах
Классическая реализация паттерна полагается на механизм вложенных классов,
Создатель делает снимки своего состояния по запросу, а также воспроизводит прошлое состояние, если подать в него готовый снимок.
Снимок — это простой объект данных, содержащий состояние создателя. Надёжней всего сделать объекты снимков неизменяемыми и передавать в них состояние только через конструктор.
Опекун должен знать, когда и зачем делать снимок создателя, а также когда его нужно восстанавливать.
Опекун может хранить историю прошлых состояний создателя в виде стека из снимков. Если понадобится сделать отмену, он возьмёт последний снимок и передаст его создателю для восстановления.
В этой реализации снимок — это внутренний класс по отношению к классу создателя, поэтому тот имеет полный доступ к его полям и методам, несмотря на то, что они объявлены приватными. Опекун же не имеет доступа ни к состоянию, ни к методам снимков и может всего лишь хранить ссылки на эти объекты.
Слайд 22Реализация с промежуточным пустым интерфейсом
Подходит для языков, не имеющих механизма вложенных классов
Реализация с промежуточным пустым интерфейсом
Подходит для языков, не имеющих механизма вложенных классов
В этой реализации создатель работает напрямую с конкретным классом снимка, а опекун — только с его ограниченным интерфейсом.
Благодаря этому достигается тот же эффект, что и в классической реализации. Создатель имеет полный доступ к снимку, а опекун — нет.
Слайд 23Снимки с повышенной защитой
Когда нужно полностью исключить доступ к состоянию Создателей и
Снимки с повышенной защитой
Когда нужно полностью исключить доступ к состоянию Создателей и
Реализация разрешает иметь несколько видов создателей и снимков. Каждому классу создателей соответствует собственный класс снимков. Ни создатели, ни снимки не позволяют прочесть их состояние.
Здесь опекун ещё более жёстко ограничен в доступе к состоянию создателей и снимков. Но с другой стороны, опекун становится независим от создателей, так как метод восстановления теперь находится в самих снимках.
Снимки теперь связаны с теми создателями, из которых они сделаны. Они по-прежнему получают состояние через конструктор. Благодаря близкой связи между классами, снимки знают, как восстановить состояние своих создателей.
Слайд 24Пример
В этом примере паттерн Снимок используется совместно с паттерном Команда и позволяет хранить резервные
Пример
В этом примере паттерн Снимок используется совместно с паттерном Команда и позволяет хранить резервные
Объекты команд выступают в роли опекунов и запрашивают снимки у редактора перед тем, как выполнить своё действие. Если потребуется отмена операции, команда сможет восстановить состояние редактора, используя сохранённый снимок.
При этом снимок не имеет публичных полей, поэтому никакой объект не сможет получить доступа его данным. Снимки связаны с определённым редактором, которых их создал и сам восстанавливает его состояние. Это позволяет программе иметь одновременно несколько объектов редакторов, например, разбитых по вкладкам.
Слайд 25Класс Редактор
// Класс создателя должен иметь специальный метод, который сохраняет состояние
//
Класс Редактор
// Класс создателя должен иметь специальный метод, который сохраняет состояние
//
class Editor is
private field text: string
private field cursorX, cursorY, selectionWidth
method setText(text) is
this.text = text
method setCursor(x, y) is
this.cursorX = cursorX this.cursorY = cursorY
method selectionWidth(width) is
this.selectionWidth = width
method saveState():EditorState is
// Снимок — неизменяемый объект, поэтому Создатель передаёт все своё
// состояние через параметры конструктора.
return new EditorState(this, text, cursorX, cursorY, selectionWidth)
Слайд 26Состояние редактора
// Снимок хранит прошлое состояние редактора.
class EditorState is
private field
Состояние редактора
// Снимок хранит прошлое состояние редактора.
class EditorState is
private field
private field text: string
private field cursorX, cursorY, selectionWidth
constructor EditorState(editor, text, cursorX, cursorY, selectionWidth) is this.editor = editor
this.text = text
this.cursorX = cursorX
= cursorY this.selection
Width = selectionWidth
// В нужный момент, владелец снимка может восстановить состояние редактора.
method restore() is
editor.setText(text) editor.setCursor(cursorX, cursorY)
editor.selectionWidth(selectionWidth)
Слайд 27Опекун
// Опекуном может выступать класс команд (см. паттерн Команда). В этом случае,
Опекун
// Опекуном может выступать класс команд (см. паттерн Команда). В этом случае,
// отмене, возвращает получателя в предыдущее состояние. class Command is
private field backup: EditorState
method backup() is
backup = editor.saveState()
method undo() is
if (backup != null)
backup.restore() // ...
Слайд 28Применимость
Когда вам нужно сохранять мгновенный снимок состояния объекта (или его части), чтобы
Применимость
Когда вам нужно сохранять мгновенный снимок состояния объекта (или его части), чтобы
Паттерн Снимок позволяет делать любое количество снимков объекта и хранить их независимо от объекта, с которого делают снимок.
Снимки часто используют не только для реализации операции отмены, но и для транзакций, когда состояние объекта нужно откатить, если операция не удалась.
Когда прямое получение состояния объекта раскрывает детали его реализации и нарушает инкапсуляцию.
Паттерн предлагает изготовить снимок самому исходному объекту, так как ему доступны все поля, даже приватные.
Слайд 29Шаги реализации
Определите класс создателя, объекты которого должны создавать снимки своего состояния.
Создайте класс
Шаги реализации
Определите класс создателя, объекты которого должны создавать снимки своего состояния.
Создайте класс
Сделайте объекты снимков неизменяемыми. Они должны получать начальные значения только один раз, через свой конструктор.
Если ваш язык программирования это позволяет, сделайте класс снимка вложенным в класс создателя.
Добавьте в класс создателя метод получения снимков. Создатель должен создавать новые объекты снимков, передавая значения своих полей через конструктор.
Сигнатура метода должна возвращать снимки через ограниченный интерфейс, если он у вас есть. Сам класс должен работать с конкретным классом снимка.
Добавьте в класс создателя метод восстановления из снимка..
Опекуны, будь то история операций, объекты команд или нечто иное, должны знать о том, когда запрашивать снимки у создателя, где их хранить, и когда восстанавливать.
Связь опекунов с создателями можно перенести внутрь снимков. В этом случае каждый снимок будет привязан к своему создателю и должен будет сам восстанавливать его состояние. Но это будет работать либо если классы снимков вложены в классы создателей, либо если создатели имеют сеттеры для установки значений своих полей.
Слайд 30Преимущества и недостатки
Не нарушает инкапсуляции исходного объекта.(+)
Упрощает структуру исходного объекта. Ему не
Преимущества и недостатки
Не нарушает инкапсуляции исходного объекта.(+)
Упрощает структуру исходного объекта. Ему не
Требует много памяти, если клиенты слишком часто создают снимки.(-)
Может повлечь дополнительные издержки памяти, если объекты, хранящие историю, не освобождают ресурсы, занятые устаревшими снимками. (-)
В некоторых языках (например, PHP, Python, JavaScript) сложно гарантировать, чтобы только исходный объект имел доступ к состоянию снимка. (-)
Слайд 31Отношения с другими паттернами
Команду и Снимок можно использовать сообща для реализации отмены операций. В этом
Отношения с другими паттернами
Команду и Снимок можно использовать сообща для реализации отмены операций. В этом
Снимок можно использовать вместе с Итератором, чтобы сохранить текущее состояние обхода структуры данных и вернуться к нему в будущем, если потребуется.
Снимок иногда можно заменить Прототипом, если объект, чьё состояние требуется сохранять в истории, довольно простой, не имеет активных ссылок на внешние ресурсы, либо их можно легко восстановить.