Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шаблоны и архитектура программ.doc
Скачиваний:
12
Добавлен:
04.05.2019
Размер:
558.08 Кб
Скачать

Команда (Command)

Шаблон Команда инкапсулирует команды в объекте таким образом, что можно управлять их выбором, ставить в очередь, отменять и выполнять иные манипуляции.

Классической иллюстрацией применения шаблона Команда является система меню любого оконного приложения. Пункты меню – это как раз и есть те команды, которые описывает шаблон. Некоторые команды в определенный момент времени доступны для выполнения, другие – нет. Заданный набор команд поддерживает функции отмены и повторного выполнения (Undo и Redo). Также обычно существует способ объединить несколько команд в одну макрокоманду.

Дизайн шаблона Команда показан на рис. 19.

Рис. 19. Дизайн шаблона Команда.

Объект Client выражает необходимость в определенных операциях в виде высокоуровневых терминов, зависящих от предметной области. Объекты Receiver знают, как выполнить требуемую операцию. Класс Command формирует интерфейс между Client и Receiver. В объекте-команде клиентские запросы ассоциируются с доступными операциями в объектах Receiver. Возможно, что клиент передает объектам Receiver некоторый контекст выполнения (или своё состояние).

При практической реализации шаблона Команда некоторые участники шаблона заменяются объектами-делегатами. Следующий пример кода – это реализация шаблона Команда для системы команд меню Paste и Print. При этом вводится логирование и поддержка отмены команд.

using System;

public delegate void Invoker();

public static class InvokerExtensions

{

private static int count;

public static int Count(this Invoker invoker)

{

return count;

}

public static void Log(this Invoker invoker)

{

count++;

}

}

public abstract class ICommand

{

public Invoker Execute, Redo, Undo;

}

public class CommandMenu

{

private class Paste : ICommand

{

public Paste(Document document)

{

Execute = delegate

{

Execute.Log();

document.Paste();

};

Redo = delegate

{

Redo.Log();

document.Paste();

};

Undo = delegate

{

Undo.Log();

document.Restore();

};

}

}

private class Print : ICommand

{

public Print(Document document)

{

Execute = delegate

{

Execute.Log();

document.Print();

};

Redo = delegate

{

Redo.Log();

document.Print();

};

Undo = delegate

{

Undo.Log();

Console.WriteLine("Cannot undo");

};

}

}

private static string clipboard;

private class Document

{

private readonly string name;

private string oldpage, page;

public Document(string name)

{

this.name = name;

}

public void Paste()

{

oldpage = page;

page += clipboard + "\n";

}

public void Restore()

{

page = oldpage;

}

public void Print()

{

Console.WriteLine("File " + name + " at " +

DateTime.Now + "\n" + page);

}

}

private static void Main()

{

var document = new Document("Greetings");

var paste = new Paste(document);

var print = new Print(document);

clipboard = "Hello, everyone";

paste.Execute();

print.Execute();

paste.Undo();

clipboard = "Bonjour, mes amis";

paste.Execute();

clipboard = "Guten morgen, meine Freunde";

paste.Redo();

print.Execute();

print.Undo();

Console.WriteLine("Logged " + paste.Execute.Count() +

" commands");

}

}