
Команда на C++
Команда — это поведенческий паттерн, позволяющий заворачивать запросы или простые операции в отдельные объекты.
Это позволяет откладывать выполнение команд, выстраивать их в очереди, а также хранить историю и делать отмену.
Сложность:
Популярность:
Применимость: Паттерн можно часто встретить в C++ коде, особенно когда нужно откладывать выполнение команд, выстраивать их в очереди, а также хранить историю и делать отмену.
Признаки применения паттерна: Классы команд построены вокруг одного действия и имеют очень узкий контекст. Объекты команд часто подаются в обработчики событий элементов GUI. Практически любая реализация отмены использует принципа команд.
Концептуальный пример
Этот пример показывает структуру паттерна Команда, а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.
main.cc: Пример структуры паттерна
/** * Интерфейс Команды объявляет метод для выполнения команд. */ class Command { public: virtual ~Command() { } virtual void Execute() const = 0; }; /** * Некоторые команды способны выполнять простые операции самостоятельно. */ class SimpleCommand : public Command { private: std::string pay_load_; public: explicit SimpleCommand(std::string pay_load) : pay_load_(pay_load) { } void Execute() const override { std::cout << "SimpleCommand: See, I can do simple things like printing (" << this->pay_load_ << ")\n"; } }; /** * Классы Получателей содержат некую важную бизнес-логику. Они умеют выполнять * все виды операций, связанных с выполнением запроса. Фактически, любой класс * может выступать Получателем. */ class Receiver { public: void DoSomething(const std::string &a) { std::cout << "Receiver: Working on (" << a << ".)\n"; } void DoSomethingElse(const std::string &b) { std::cout << "Receiver: Also working on (" << b << ".)\n"; } }; /** * Но есть и команды, которые делегируют более сложные операции другим объектам, * называемым «получателями». */ class ComplexCommand : public Command { /** * @var Receiver */ private: Receiver *receiver_; /** * Данные о контексте, необходимые для запуска методов получателя. */ std::string a_; std::string b_; /** * Сложные команды могут принимать один или несколько объектов-получателей * вместе с любыми данными о контексте через конструктор. */ public: ComplexCommand(Receiver *receiver, std::string a, std::string b) : receiver_(receiver), a_(a), b_(b) { } /** * Команды могут делегировать выполнение любым методам получателя. */ void Execute() const override { std::cout << "ComplexCommand: Complex stuff should be done by a receiver object.\n"; this->receiver_->DoSomething(this->a_); this->receiver_->DoSomethingElse(this->b_); } }; /** * Отправитель связан с одной или несколькими командами. Он отправляет запрос * команде. */ class Invoker { /** * @var Command */ private: Command *on_start_; /** * @var Command */ Command *on_finish_; /** * Инициализация команд. */ public: ~Invoker() { delete on_start_; delete on_finish_; } void SetOnStart(Command *command) { this->on_start_ = command; } void SetOnFinish(Command *command) { this->on_finish_ = command; } /** * Отправитель не зависит от классов конкретных команд и получателей. * Отправитель передаёт запрос получателю косвенно, выполняя команду. */ void DoSomethingImportant() { std::cout << "Invoker: Does anybody want something done before I begin?\n"; if (this->on_start_) { this->on_start_->Execute(); } std::cout << "Invoker: ...doing something really important...\n"; std::cout << "Invoker: Does anybody want something done after I finish?\n"; if (this->on_finish_) { this->on_finish_->Execute(); } } }; /** * Клиентский код может параметризовать отправителя любыми командами. */ int main() { Invoker *invoker = new Invoker; invoker->SetOnStart(new SimpleCommand("Say Hi!")); Receiver *receiver = new Receiver; invoker->SetOnFinish(new ComplexCommand(receiver, "Send email", "Save report")); invoker->DoSomethingImportant(); delete invoker; delete receiver; return 0; }
Output.txt: Результат выполнения
Invoker: Does anybody want something done before I begin? SimpleCommand: See, I can do simple things like printing (Say Hi!) Invoker: ...doing something really important... Invoker: Does anybody want something done after I finish? ComplexCommand: Complex stuff should be done by a receiver object. Receiver: Working on (Send email.) Receiver: Also working on (Save report.)