Паттерн Команда

Паттерн Команда относится к поведенческим паттернам проектирования.

Это паттерн с которым я сижу дольше остальных, он настолько прост, что очень сложен. Но лично я нахожу прелесть самообучения в том что у тебя есть все время мира чтобы исследовать определенный вопрос под всеми углами.

Итак, в GoF применимость описывается достаточно лаконично и понятно:
Инкапсулирует запрос как объект, позволяя настраивать (parameterize) клиентов с разными запросами, использовать очереди, логировать запросы и осуществлять операции отмены.

Теперь реализуем простой вариант команды из описания:

 
string fakeTrumpsRequest = “SELECT * from Users where name beginsWith DonaldTrump”
 

Мы инкапсулировали запрос в объект класса строки, ей можно настраивать клиентов, добавлять команды в очередь, логировать, осуществлять отмену (с использованием паттерна “Снимок”)

Мне кажется этого вполне достаточно для осуществления запросов SQL и подобных, однако дальше начинаются детали реализации, разные варианты применения, также очень сильно разнится кодовая база паттерна, роли клиентов, добавляются вспомогательные классы.

Матчасть

Паттерн команда начинается с протокола Команды, который содержит единственный метод execute(). Дальше идет Конкретная Команда и Ресивер, КК реализует операцию над Ресивером, описывает связь между Ресивером и действием. Ничего непонятно? Мне тоже, но поехали дальше. Клиент создает экземпляр Конкретной Команды, связывает ее с Ресивером. Инвокер – объект который осуществляет процесс запуска Команды.

Теперь попробуем разобраться на примере, допустим мы хотим обновить myOS на телефоне myPhone, для этого мы запускаем приложение myOS_Update!, в нем нажимаем кнопку Update Now!, через 10 секунд система сообщит об успешном обновлении.

Клиентом в примере выше выступает приложение myOS_Update!, Инвокер это кнопка “Update Now!”, он запускает Конкретную Команду обновления системы с помощью метода execute(), которая обращается к Ресиверу – демону обновления операционной системы.

Пример использования

Допустим UI приложения myOS_Update! настолько хорош, что его решили продавать как отдельный продукт для предоставления интерфейса обновления других операционных систем. В таком случае мы реализуем приложение с поддержкой расширения через библиотеки, в библиотеках будут реализации Конкретных Команд, Ресиверов, оставим статичные/неизменяемые Инвокер, Клиент, протокол Команды.

Таким образом отпадает необходимость в осуществлении поддержки изменяемого кода, так как наш код останется неизменным, проблемы могут возникнут лишь при реализации на стороне клиентов, из-за ошибок в коде их Конкретных Команд и Ресиверов. Также в такой реализации отсутствует необходимость передавать исходный код основного приложения, то есть мы осуществили инкапсуляцию команд и взаимодействия UI с помощью паттерна Команда.

Источники

https://refactoring.guru/ru/design-patterns/command
https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612