Անվան այլ կիրառումների համար տե՛ս՝ Հրաման (այլ կիրառումներ)

**Հրաման** (անգլ.՝ Command pattern), վարքագծային նախագծման ձևանմուշ, որն օգտագործվում է օբյեկտ կողմնորոշված ծրարգավորման մեջ գործողությունը ներկայացնելու համար։ Հրամանի օբյեկտն իր մեջ պարունակում է գործողությունն իր պարամետրերով։

Ընդհանուր հասկացողություններ
----------------------------

* Client - հայցող
* Instance - նմուշ
* Implementation - իրականացում
* Product - արգասիք

Նպատակ
------

Սրուկտուրայի ստեղծում, որտեղ ուղարկող և ստացող դասերը ուղիղ գծով միմյանց հետ կապված չեն։ Կազմակերպում է դասի հետադարձ կանչ, որն ներառում է ուղարկող դաս։

Նկարագրություն
--------------

Վարքագծային այս ձևանմուշը հայտնի է նաև Action (գործողություն) անվանումով։

Ապահովում է հրամանի մշակումը օբյեկտի տեսքով, որը թույլ է տալիս հիշել այն և որպես պարամետր ներկայացնել դասերի մեթոդներին, ինչպես նաև վերադարձնել նրա արժեքը։

Օրինակ տպիչի գրադարանը կարող է ունենա PrintJob դաս։ Դրա համար կարելի է ստեղծել PrintJob օբյեկտ, դնել անհրաժեշտ պարամետրերը և կանչել մեթոդը, որն անմիջականորեն խնդիրը կուղարկի տպման։

Օրինակներ
---------

### С++

```
#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Document
{
 vector<string> data; 
public:
 void Insert( int line, const string & str )
 {
 if ( line <= data.size() )
 data.insert( data.begin() + line, str ); 
 else
 cout << "Error!" << endl; 
 }

 void Remove( int line )
 {
 if( !( line>data.size() ) )
 data.erase( data.begin() + line ); 
 else
 cout << "Error!" << endl; 
 }

 string & operator [] ( int x )
 {
 return data[x]; 
 }

 void Show()
 {
 for( int i = 0; i<data.size(); ++i )
 {
 cout << i + 1 << ". "<< data[i] << endl; 
 }
 }
};

class Command
{
protected:
 Document \* doc; 
public:
 virtual void Execute() = 0; 
 virtual void unExecute() = 0;

 void setDocument( Document \* \_doc )
 {
 doc = \_doc; 
 }
};

class InsertCommand : public Command
{
 int line; 
 string str; 
public:
 InsertCommand( int \_line, const string & \_str ): line( \_line ), str( \_str ) {}

 void Execute()
 {
 doc->Insert( line, str ); 
 }

 void unExecute()
 {
 doc->Remove( line ); 
 }
};

class Receiver
{
 vector<Command\*> DoneCommands; 
 Document doc; 
 Command\* command; 
public:
 void Insert( int line, string str )
 {
 command = new InsertCommand( line, str ); 
 command->setDocument( &doc ); 
 command->Execute(); 
 DoneCommands.push\_back( command ); 
 }

 void Undo()
 {
 if( DoneCommands.size() == 0 )
 {
 cout << "There is nothing to undo!" << endl; 
 }
 else
 {
 command = DoneCommands.back(); 
 DoneCommands.pop\_back(); 
 command->unExecute();
 // Don't forget to delete command!!!
 delete command;
 }
 }

 void Show() 
 {
 doc.Show(); 
 }
};

int main()
{
 char s = '1'; 
 int line, line\_b; 
 string str; 
 Receiver res; 
 while( s!= 'e' )
 {
 cout << "What to do: \n1.Add a line\n2.Undo last command" << endl; 
 cin >> s; 
 switch( s )
 {
 case '1':
 cout << "What line to insert: "; 
 cin >> line; 
 --line; 
 cout << "What to insert: "; 
 cin >> str; 
 res.Insert( line, str ); 
 break; 
 case '2':
 res.Undo(); 
 break; 
 }
 cout << "$$$DOCUMENT$$$" << endl; 
 res.Show(); 
 cout << "$$$DOCUMENT$$$" << endl; 
 }
}

```

### С#

```
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)
 \_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();

 if (\_current < \_commands.Count)
 {
 // если "внутри undo" мы запускаем новую операцию, 
 // надо обрубать список команд, следующих после текущей, 
 // иначе undo/redo будут некорректны
 \_commands.RemoveRange(\_current, \_commands.Count - \_current);
 }

 // Добавляем операцию к списку отмены
 \_commands.Add(command);
 \_current++;
 }
 }
}

```

### Java

```
/\*the Invoker class\*/

public class Switch {
 private Command flipUpCommand;
 private Command flipDownCommand;

 public Switch(Command flipUpCommand,Command flipDownCommand){
 this.flipUpCommand=flipUpCommand;
 this.flipDownCommand=flipDownCommand;
 }

 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();
 }
}

```

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * դ
* ք
* խ
Նախագծման ձևանմուշներ |
| --- |
|  |
| ԳօՖիձևանմուշներ | 

|  |  |
| --- | --- |
| Ստեղծող | Աբստրակտ ֆաբրիկա • Կառուցող • Ֆաբրիկային մեթոդ • Նախատիպ • Եզակի օգտագործման |
| Կառուցվածքային | Ադապտեր • Կամուրջ • Կազմող • Դեկորատոր • Ճակատ • Հարմարեցնող • Պրոքսի |
| Վարքագծային | Պարտականությունների շղթա • Հրաման • Թարգմանիչ • Իտերատոր • Միջնորդ • Պահպանող • Դիտորդ • Վիճակ • Մարտավարություն • Կաղապարային մեթոդ • Այցելող |

 |
|  |
| Ստեղծող ձևանմուշներ | Ծույլ բեռնում • Բազմակի օգտագործման • Օբյեկտների ավազան • Ռեսուրսի ստանալը ինիցիալիզացիա է |
|  |
| Կառուցվածքային ձևանմուշներ | Ճակատը հսկող • Մոդուլ |
|  |
| Համաձայնեցման ձևանմուշներ | Ակտիվ օբյեկտ • Հենվող • Մեկուսացում կրկնակի ստուգումով • Ասինքրոն կանչի մեթոդ • Պահպանվող կախոց • Ռեգիստրացնող • Կողպեքավորող • Մոնիտոր • Նախագործող • Ապագործող • Ընթերցողներ-գրողի կողպեք • Պլանավորման • Հոսքերի ավազանի • Հոսքերի լոկալ հիշողություն |
|  |
| Ճարտարապետական ձևանմուշներ | Ճակատը հսկող ձևանմուշ • Զավթող ձևանմուշ • ձևանմուշի ներկայացման վերահսկում • Բազմաշերտ • Հատկորոշում • Հրատարակող-ստորագրող • Մերկ օբյեկտներ • Ծառայության լոկատոր • Ակտիվ գրառման • Բազմության իդենտիֆիկացման • Data access object • Data transfer object |
|  |
| Այլ ձևանմուշներ | Կախվածության ներդնում • Mock օբյեկտ • Զրոյական օբյեկտ • Ծառայող • Թունելային տարատեսակի |

 |



|  |
| --- |
| *Այս հոդվածի կամ նրա բաժնի որոշակի հատվածի սկզբնական կամ ներկայիս տարբերակը վերցված է Քրիեյթիվ Քոմմոնս Նշում–Համանման տարածում 3.0 (Creative Commons BY-SA 3.0) ազատ թույլատրագրով թողարկված Հայկական սովետական հանրագիտարանից  (հ․ 6, էջ 619)։*  |