Команда (Command)

Материал из Вики ИТ мехмата ЮФУ
Версия от 08:44, 2 августа 2014; Admin (обсуждение | вклад) (Описание)

Перейти к: навигация, поиск

К основной странице курса

Другое имя

Action (действие), Transaction (транзакция)

Назначение

Упаковка действий (запросов) в объекты, позволяя ставить запросы в очередь, выполнять логирование, комбинирование действий, поддерживать отмену операций.

Описание

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

Реализация

Диаграмма классов

CommandCommon.png

Участники

  • Command - команда

Объявляет интерфейс для выполнения операции, состоящий из метода Execute и, возможно, UnExecute

  • ConcreteCommand - конкретная команда

Реализует метод Execute, вызывая методы Receiverа

  • Client - клиент

Создает объект класса ConcreteCommand и устанавливает его получателя (Receiverа). Получатель команды - это дурацкое непонятное название, смысл которого в следующем. Receiver называется получателем команды если команда вызывает его методы.

  • Invoker - инициатор

Обращается к команде для выполнения запроса (вызывает ее метод Execute)

  • Receiver - получатель

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

Пример

Этот пример в WDE

using System;
using System.Collections.Generic;

class AruthmeticUnit // Receiver
{
  private double res = 0;
  public void Add(double x)
  {
    res += x;
  }
  public void Sub(double x)
  {
    res -= x;
  }
  public void Div(double x)
  {
    res /= x;
  }
  public void Mult(double x)
  {
    res *= x;
  }
  public double Result
  {
    get { return res; }
  }
}

abstract class Command
{
  public readonly AruthmeticUnit unit;
  public Command(AruthmeticUnit unit)
  {
    this.unit = unit;
  }
  public abstract void Execute();
}

class BinaryCommand: Command
{
  private char op;
  private double x;
  public BinaryCommand(AruthmeticUnit unit, char op, double x): base(unit)
  {
    this.op = op;
    this.x = x;
  }
  public override void Execute()
  {
    switch (op)
    {
      case '+': 
        unit.Add(x);
        break;
      case '-': 
        unit.Sub(x);
        break;
      case '*': 
        unit.Mult(x);
        break;
      case '/': 
        unit.Div(x);
        break;
    }
  }
}

class ChangeSignCommand: Command
{
  public ChangeSignCommand(AruthmeticUnit unit): base(unit)
  { }
  public override void Execute()
  {
    unit.Mult(-1);
  }
}

class My // Одновременно Client (создает команды и Receiverа) и Invoker (выполняет команды)
{
  public static void Main()
  {
    // Действия Clientа
    var unit = new AruthmeticUnit();
    var l = new List<Command>();
    l.Add(new BinaryCommand(unit,'+',2));
    l.Add(new BinaryCommand(unit,'*',3));
    l.Add(new BinaryCommand(unit,'-',1));
    l.Add(new BinaryCommand(unit,'*',2));
    l.Add(new ChangeSignCommand(unit));
    
    // Действия Invokerа
    foreach (var c in l)
      c.Execute();
    Console.WriteLine(unit.Result);  
  }
}

Нетрудно реализовать метод UnExecute, выподняющий противоположное действие. Для отката действий необходимо выполнить UnExecute для команд в обратном порядке.

Достоинства и недостатки

Варианты