Псевдокод
В этом примере паттерн Команда служит для ведения истории выполненных операций, позволяя отменять их, если потребуется.
Пример реализации отмены в текстовом редакторе.
Команды, которые меняют состояние редактора (например, команда вставки текста из буфера обмена), сохраняют копию состояния редактора перед выполнением действия. Копии выполненных команд помещаются в историю команд, откуда они могут быть доставлены, если нужно будет сделать отмену операции.
Классы элементов интерфейса, истории команд и прочие не зависят от конкретных классов команд, так как работают с ними через общий интерфейс. Это позволяет добавлять в приложение новые команды, не изменяя существующий код.
// Абстрактная команда задаёт общий интерфейс для конкретных
// классов команд и содержит базовое поведение отмены операции.
Abstract class Command is
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()
// Конкретные команды.
class CopyCommand extends Command is
// Команда копирования не записывается в историю, так как
// она не меняет состояние редактора.
method execute() is
app.clipboard = editor.getSelection()
Return false
class CutCommand extends Command is
// Команды, меняющие состояние редактора, сохраняют
|
// состояние редактора перед своим действием и сигнализируют
// об изменении, возвращая true.
method execute() is
saveBackup()
app.clipboard = editor.getSelection()
editor.deleteSelection()
Return true
class PasteCommand extends Command is
method execute() is
saveBackup()
editor.replaceSelection(app.clipboard)
Return true
// Отмена — это тоже команда.
class UndoCommand extends Command is
method execute() is
app.undo()
Return false
// Глобальная история команд — это стек.
Class CommandHistory is
private field history: array of Command
// Последний зашедший...
method push(c: Command) is
// Добавить команду в конец массива-истории.
//...выходит первым.
method pop():Command is
// Достать последнюю команду из массива-истории.
// Класс редактора содержит непосредственные операции над
// текстом. Он отыгрывает роль получателя – команды делегируют
// ему свои действия.
Class Editor is
field text: string
method getSelection() is
// Вернуть выбранный текст.
method deleteSelection() is
// Удалить выбранный текст.
method replaceSelection(text) is
// Вставить текст из буфера обмена в текущей позиции.
// Класс приложения настраивает объекты для совместной работы.
// Он выступает в роли отправителя — создаёт команды, чтобы
// выполнить какие-то действия.
Class Application is
field clipboard: string
field editors: array of Editors
field activeEditor: Editor
field history: CommandHistory
// Код, привязывающий команды к элементам интерфейса, может
// выглядеть примерно так.
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()
Применимость
Когда вы хотите параметризовать объекты выполняемым действием.