Архів категорії: Паттерни

Паттерни проектування. Прийоми об’єктно-орієнтованого програмування

Patterns. Паттерн 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;
}