Հրաման (նախագծման ձևանմուշ)

Վիքիպեդիայից՝ ազատ հանրագիտարանից
Անվան այլ կիրառումների համար տե՛ս՝ Հրաման (այլ կիրառումներ)
Հրաման
ՏեսակՎարքագծային
Նշանակությունօբյեկտի տեսքով հրամանները մշակելու համար
Նկարագրությունը ԳօՖի
"Design Patterns" գրքում
Այո

Հրաման (անգլ.՝ 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();
   }
}
Այս հոդվածի կամ նրա բաժնի որոշակի հատվածի սկզբնական կամ ներկայիս տարբերակը վերցված է Քրիեյթիվ Քոմմոնս Նշում–Համանման տարածում 3.0 (Creative Commons BY-SA 3.0) ազատ թույլատրագրով թողարկված Հայկական սովետական հանրագիտարանից  (հ․ 6, էջ 619