Command

Материал из Википедии — свободной энциклопедии

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

Команда — шаблон проектирования, используемый при объектно-ориентированном программировании, представляющий действие. Объект команды заключает в себе само действие и его параметры.

Содержание

[править] Описание

Название команда
Английское название command
Диаграмма Файл:command.gif
Тип поведенческий
Назначение для обработки команды в виде объекта



Родственные шаблоны Composite/Компоновщик, Memento, Прототип, Singleton

Обеспечивает обработку команды в виде объекта, что позволяет сохранять её, передавать в качестве параметра методам, а также возвращать её в виде результата, как и любой другой объект.


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

[править] Примеры

[править] Пример С#

using System;
using System.Collections.Generic;
 
namespace Command
{
 
  class MainApp
  {
    static void Main()
    {
      // Создаем пользователя.
      User user = new User();
 
      // Пусть он что-нибудь сделает.
      user.Compute('+', 100);
      user.Compute('-', 50);
      user.Compute('*', 10);
      user.Compute('/', 2);
 
      // Отменяем 4 команды
      user.Undo(4);
 
      // Вернём 3 отменённые команды.
      user.Redo(3);
 
      // Ждем ввода пользователя и завершаемся.
      Console.Read();
    }
  }
 
  // "Command" : абстрактная Команда
 
  abstract class Command
  {
    public abstract void Execute();
    public abstract void UnExecute();
  }
 
  // "ConcreteCommand" : конкретная команда
 
  class CalculatorCommand : Command
  {
    char @operator;
    int operand;
    Calculator calculator;
 
    // Constructor
    public CalculatorCommand(Calculator calculator,
      char @operator, int operand)
    {
      this.calculator = calculator;
      this.@operator = @operator;
      this.operand = operand;
    }
 
    public char Operator
    {
      set{ @operator = value; }
    }
 
    public int Operand
    {
      set{ operand = value; }
    }
 
    public override void Execute()
    {
      calculator.Operation(@operator, operand);
    }
 
    public override void UnExecute()
    {
      calculator.Operation(Undo(@operator), operand);
    }
 
    // Private helper function : приватные вспомогательные функции
    private char Undo(char @operator)
    {
      char undo;
      switch(@operator)
      {
        case '+': undo = '-'; break;
        case '-': undo = '+'; break;
        case '*': undo = '/'; break;
        case '/': undo = '*'; break;
        default : undo = ' '; break;
      }
      return undo;
    }
  }
 
  // "Receiver" : получатель
 
  class Calculator
  {
    private int curr = 0;
 
    public void Operation(char @operator, int operand)
    {
      switch(@operator)
      {
        case '+': curr += operand; break;
        case '-': curr -= operand; break;
        case '*': curr *= operand; break;
        case '/': curr /= operand; break;
      }
      Console.WriteLine(
        "Current value = {0,3} (following {1} {2})",
        curr, @operator, operand);
    }
  }
 
  // "Invoker" : вызывающий
 
  class User
  {
    // Initializers
    private Calculator calculator = new Calculator();
    private List<Command> commands = new List<Command>();
 
    private int current = 0;
 
    public void Redo(int levels)
    {
      Console.WriteLine("\n---- Redo {0} levels ", levels);
 
      // Делаем возврат операций
      for (int i = 0; i < levels; i++)
        if (current < commands.Count - 1)
          commands[current++].Execute();
    }
 
    public void Undo(int levels)
    {
      Console.WriteLine("\n---- Undo {0} levels ", levels);
 
      // Делаем отмену операций
      for (int i = 0; i < levels; i++)
        if (current > 0)
          commands[--current].UnExecute();
    }
 
    public void Compute(char @operator, int operand)
    {
 
      // Создаем команду операции и выполняем её
      Command command = new CalculatorCommand(
        calculator, @operator, operand);
      command.Execute();
 
      // Добавляем операцию к списку отмены
      commands.Add(command);
      current++;
    }
  }
}

[править] Пример Java

/*the Invoker class*/
public class Switch {
    private Command flipUpCommand;
    private Command flipDownCommand;
 
    public Switch(Command flipUpCmd,Command flipDownCmd){
            this.flipUpCommand=flipUpCmd;
            this.flipDownCommand=flipDownCmd;
           }
 
    public void flipUp(){
         flipUpCommand.execute();
    }
 
    public void flipDown(){
         flipDownCommand.execute();
    }
}
 
/*Receiver class*/
 
public class Light{
     public Light(){  }
 
     public void turnOn(){
        System.out.println("The light is on");
     }
 
     public void turnOff(){
        System.out.println("The light is off");
     }
}
 
 
/*the Command interface*/
 
public interface Command{
    void execute();
}
 
 
/*the Command for turning on the light*/
 
public class TurnOnLightCommand implements Command{
   private Light theLight;
 
   public TurnOnLightCommand(Light light){
        this.theLight=light;
       }
 
   public void execute(){
      theLight.turnOn();
   }
}
 
/*the Command for turning off the light*/
 
public class TurnOffLightCommand implements Command{
   private Light theLight;
 
   public TurnOffLightCommand(Light light){
        this.theLight=light;
       }
 
   public void execute(){
      theLight.turnOff();
   }
}
 
/*The test class*/
public class TestCommand{
   public static void main(String[] args){
       Light l=new Light();
       Command switchUp=new TurnOnLightCommand(l);
       Command switchDown=new TurnOffLightCommand(l);
 
       Switch s=new Switch(switchUp,switchDown);
 
       s.flipUp();
       s.flipDown();
   }
}

[править] Пример JavaScript

// Command: абстрактная Команда
function Command() {
	this.execute = function() {};
	this.unExecute = function() {};
}
 
// ConcreteCommand: конкретная команда
function CalculatorCommand() {
	var calculator;
	var operator;
	var operand;
 
	this.execute = function(newCalculator, newOperator, newOperand) {
		// установка параметров команды
		if (typeof(newCalculator)=="object" && typeof(newOperator)=="string" && typeof(newOperand)=="number") {
			calculator = newCalculator;
			operator = newOperator;
			operand = newOperand;
		}
		// исполнение команды
		calculator.operation(operator, operand);
	};
	this.unExecute = function() {
		// исполнение обратной команды
		calculator.operation(undo(operator), operand); 
	};
 
	function undo(operator) {
		// функция вернет оператор, обратный переданному
		// при желании, можно воспользоваться замыканием и не передавать оператор
		switch(operator) {
	        case '+': return '-'; break;
	        case '-': return '+'; break;
		}
		return ' '; // результат по умолчанию
	}
}
CalculatorCommand.prototype = new Command();
CalculatorCommand.prototype.constructor = CalculatorCommand;
 
// Receiver: получатель
function Calculator() {
	var val = 0;
 
	this.operation = function(operator, operand) {
		// производим операцию
		switch(operator) {
	        case '+': 
				val += operand; 
				debug(operator, operand);
			break;
	        case '-': 
				val -= operand; 
				debug(operator, operand);
			break;
			default:
				alert("Неизвестный оператор");
			break;
		}
	};
 
	function debug(operator, operand) {
		alert("Текущее значение: "+ val +"\nОперация: "+ operator + operand);
	}
}
 
// Invoker: вызывающий
function User() {
	var calculator = new Calculator();
	var commands = []; // массив команд
	current = 0;       // номер текущей команды
 
	this.compute = function(operator, operand) {
		var newCommand = new CalculatorCommand();
		if (current<commands.length-1) {
			// если "внутри undo" мы запускаем новую операцию, 
			// надо обрубать список команд, следующих после текущей, 
			// иначе undo/redo будут некорректны
			commands.splice(current);
		}
		newCommand.execute(calculator, operator, operand);
		commands.push(newCommand);
		current++;
	};
 
	this.undo = function(levels) {
		alert("отмена ("+ levels +")");
		for (i=0; i<levels; i++) {
			if (current > 0) {
				commands[--current].unExecute();
			}
		}
	};
 
	this.redo = function(levels) {
		alert("возврат ("+ levels +")");
		for (i=0; i<levels; i++) {
			if (current < commands.length) {
				commands[current++].execute();
			}
		}
	};
}
 
 
// использование
var u = new User();
u.compute("+", 2); // 2, "+2"
u.compute("+", 3); // 5, "+3"
u.compute("-", 1); // 4, "-1"
u.compute("+", 6); // 10, "+6"
u.undo(3);         // 4, "-6"
                   // 5, "+1"
                   // 2, "-3"
u.redo(2);         // 5, "+3"
                   // 4, "-1"
u.undo(2);         // 5, "+1"
                   // 2, "-3"
u.compute("+", 8); // 10, "+8"
u.undo(1);         // 2, "-8"
u.redo(2);         // 10, "+8"
                   // превышение длинны commands
u.compute("+", 9); // 19, "+9"


Поведенческие шаблоны проектирования

Interpreter/Интерпретатор | Template Method/Шаблонный метод | Command/Команда | Chain of Responsibility/Цепочка обязанностей | Iterator/Итератор, Cursor | Mediator/Посредник | Memento/Хранитель, Token | Observer/Наблюдатель, Listener | State/Состояние | Strategy/Стратегия | Visitor/Посетитель | Event listener | Single-serving visitor | Hierarchical visitor |

Источник — «http://ru.wikipedia.org/wiki/Command»