Паттерн «Команда» (Command)
Categories:
💻 Programming
Назначение: инкапсулирует запрос как объект, позволяя тем самым задавать параметры клиентов для обработки соответствующих запросов, ставить запросы в очередь или протоколировать их, а также поддерживать отмену операций.
Паттерн «Команда» позволяет спрятать действие в объекте и отвязать источник этого действия от места его исполнения. Классический пример — проектирование пользовательского интерфейса. Пункт меню не должен знать, что происходит при его активизации пользователем, он должен знать лишь о некотором действии, которое нужно выполнить при нажатии кнопки.
Когда использовать Паттерн Command
- Когда необходимо обеспечить выполнение очереди запросов, а также их возможную отмену.
- Когда надо поддерживать логгирование изменений в результате запросов. Использование логов может помочь восстановить состояние системы - для этого необходимо будет использовать последовательность запротоколированных команд.
- Когда необходимо параметризировать объекты выполняемым действием, ставить запросы в очередь или поддерживать операции отмены (undo) и повтора (redo) действий.
UML схема паттерна "Команда":
Реализация шаблона "команда" на C#
using System;
namespace DoFactory.GangOfFour.Command.Structural
{
/// <summary>
/// MainApp startup class for Structural
/// Command Design Pattern.
/// </summary>
class MainApp
{
/// <summary>
/// Entry point into console application.
/// </summary>
static void Main()
{
// Create receiver, command, and invoker
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
// Set and execute command
invoker.SetCommand(command);
invoker.ExecuteCommand();
// Wait for user
Console.ReadKey();
}
}
/// <summary>
/// The 'Command' abstract class
/// </summary>
abstract class Command
{
protected Receiver receiver;
// Constructor
public Command(Receiver receiver)
{
this.receiver = receiver;
}
public abstract void Execute();
}
/// <summary>
/// The 'ConcreteCommand' class
/// </summary>
class ConcreteCommand : Command
{
// Constructor
public ConcreteCommand(Receiver receiver) :
base(receiver)
{
}
public override void Execute()
{
receiver.Action();
}
}
/// <summary>
/// The 'Receiver' class
/// </summary>
class Receiver
{
public void Action()
{
Console.WriteLine("Called Receiver.Action()");
}
}
/// <summary>
/// The 'Invoker' class
/// </summary>
class Invoker
{
private Command _command;
public void SetCommand(Command command)
{
this._command = command;
}
public void ExecuteCommand()
{
_command.Execute();
}
}
}
Примеры в .NET Framework
- ICommand в WPF, на основе которых строится привязка операций к событиям пользовательского интерфейса;
- IDbCommand в ADO.NET инкапсулирует операцию, исполняемую на стороне СУБД;
- Объект класса Task<T> принимает делегат Func<T>, который можно рассматривать в виде команды, которая будет исполнена в будущем для получения результата задачи.
Comments:
Please log in
to be able add comments.
👍