Паттерн Command. Реализация структуры для двух получателей

Паттерн Command. Реализация структуры для двух получателей. Пример на C++

Демонстрируется пример программы на языке C++, реализующей паттерн Command для двух получателей.

 

1. Условие задачи

Используя язык C++ реализовать паттерн Command для двух получателей, структура которого изображена на рисунке 1.

Паттерн Command. Структура для двух получателей команды

Рисунок 1. Паттерн Command. Структура для двух получателей команды

 

2. Участники

Участники паттерна:

  • Client – клиент, которым в программе выступает функция main();
  • Command – абстрактный класс, представляющий собой интерфейс между вызывающим кодом и конкретной командой;
  • ConcreteCommand1, ConcreteCommand2 – классы, соответствующие конкретным командам;
  • Invoker – класс, вызывающий конкретную команду через ссылку на интерфейс Command;
  • Receiver – класс, объект которого получается конкретной командой ConcreteCommand1 или ConcreteCommand2.

 

3. Реализация на C++

 

// Паттерн Command (Мотивация)
#include <iostream>
using namespace std;

// Класс, который конкретная команда получает
class Receiver
{
public:
  void Action1()
  {
    cout << "Receiver::Action1()" << endl;
  }

  void Action2()
  {
    cout << "Receiver::Action2()" << endl;
  }
};

//
class Command
{
public:
  // Операция
  virtual void Execute() {}

protected:
  // Конструктор
  Command() { }
};

// Класс выполнения конкретной команды
class ConcreteCommand1 : public Command
{
private:
  Receiver* receiver;

public:
  // Конструктор
  ConcreteCommand1(Receiver* _receiver)
  {
    receiver = _receiver;
  }

  void Execute()
  {
    receiver->Action1();
  }
};

class ConcreteCommand2 : public Command
{
private:
  Receiver* receiver;

public:
  // Конструктор
  ConcreteCommand2(Receiver* _receiver)
  {
    receiver = _receiver;
  }

  void Execute()
  {
    receiver->Action2();
  }
};

// Класс, в котором содержится метод вызова
// той или иной команды.
// Этот класс сохраняет объект типа ConcreteCommand
class Invoker
{
private:
  // Команда
  Command* command;

public:
  // Конструктор
  Invoker(Command* _command = nullptr)
  {
    command = _command;
  }

  // Вызов метода
  void Invoke()
  {
    command->Execute();
  }

  // Метод, устанавливающий команду
  void SetCommand(Command* _command)
  {
    command = _command;
  }
};

void main()
{
  // Клиент (Client)
  Receiver* receiver = new Receiver;

  // Создать команды
  ConcreteCommand1* command1 = new ConcreteCommand1(receiver);
  ConcreteCommand2* command2 = new ConcreteCommand2(receiver);

  // Создать вызывающий класс
  Invoker* invoker = new Invoker;

  // Организация меню
  int cmd;
  while (true)
  {
    cout << "Enter command (1-3): 1 - Command-1, 2 - Command-2, 3 - Exit" << endl;
    cin >> cmd;

    if (cmd == 1)
    {
      invoker->SetCommand(command1);
      invoker->Invoke();  // command1->Execute()
    }

    if (cmd == 2)
    {
      invoker->SetCommand(command2);
      invoker->Invoke();  // command2->Execute()
    }

    if (cmd == 3)
      break;
  }

  if (invoker != nullptr)
    delete invoker;
  if (command1)
    delete command1;
  if (command2)
    delete command2;

  if (receiver != nullptr)
    delete receiver;
}