Команда (шаблон проектування)
Команда (англ. Command) — шаблон проектування, відноситься до класу шаблонів поведінки. Також відомий як Дія (англ. Action), Транзакція (англ. Transaction).
Призначення
Інкапсулює запит у формі об'єкта, дозволяючи тим самим задавати параметри клієнтів для обробки відповідних запитів, ставити запити у чергу або протоколювати їх, а також підтримувати скасовування операцій.
Мотивація
Застосовність
Слід використовувати шаблон Команда коли:
- треба параметризувати об'єкти дією. У процедурній мові таку параметризацію можна виразити за допомогою функції оберненого виклику, тобто такою функцією, котра реєструється, щоби бути викликаною пізніше. Команди є об'єктно-орієнтованою альтернативою функціям оберненого виклику;
- визначати, ставити у чергу та виконувати запити у різний час. Строк життя об'єкта Команди не обов'язково залежить від строку життя початкового запиту. Якщо отримувача вдається реалізувати таким чином, щоб він не залежав від адресного простору, то об'єкт-команду можна передати іншому процесу, котрий займеться його виконанням;
- потрібна підтримка скасовування операцій. Операція Execute об'єкта Команда може зберегти стан, що необхідний для відкочення дій, виконаних Командою. У цьому разі у інтерфейсі класу Command повинна бути додаткова операція Unexecute, котра скасовує дії, виконанні попереднім викликом операції Execute. Виконані команди зберігаються у списку історії. Для реалізації довільної кількості рівней скасування та повтору команд треба обходити цей список відповідно в оберненому та прямому напрямках, викликаючи під час відвідування кожного елементу операцію Unexecute або Execute;
- підтримати протоколювання змін, щоб їх можна було виконати повторно після аварійної зупинки системи. Доповнивши інтерфейс класу Command операціями зберігання та завантаження, можна вести протокол змін у внутрішній пам'яті. Для поновлення після збою треба буде завантажити збереженні команди з диску та повторно виконати їх за допомогою операції Execute;
- треба структурувати систему на основі високорівневих операцій, що побудовані з примітивних. Така структура є типовою для інформаційних систем, що підтримують трансакції. Трансакція інкапсулює множину змін даних. Шаблон Команда дозволяє моделювати трансакції. В усіх команд є спільний інтерфейс, що надає можливість працювати однаково з будь-якими трансакціями. За допомогою цього шаблону можна легко додавати у систему нові види трансакцій.
Структура
UML діаграма, що описує структуру шаблону проектування Команда
- Command — команда:
- оголошує інтерфейс для виконання операції;
- ConcreteCommand — конкретна команда:
- визначає зв'язок між об'єктом-отримувачем Receiver та дією;
- реалізує операцію Execute шляхом виклику відповідних операцій об'єкта Receiver;
- Client — клієнт:
- створює об'єкт класу ConcreteCommand та встановлює його отримувача;
- Invoker — викликач:
- звертається до команди щоб та виконала запит;
- Receiver — отримувач:
- має у своєму розпорядженні усю інформацію про способи виконання операцій, необхідних для задоволення запиту. У ролі отримувача може виступати будь-який клас.
Відносини
UML діаграма, що описує взаємовідносини поміж об'єктів шаблону проектування Команда
- клієнт створює об'єкт ConcreteCommand та встановлює для нього отримувача;
- викликач Invoker зберігає об'єкт ConcreteCommand;
- викликач надсилає запит, викликаючи операцію команди Execute. Якщо підтримується скасування виконаних дій, то ConcreteCommand перед викликом Execute зберігає інформацію про стан, достатню для виконання скасування;
- об'єкт ConcreteCommand викликає операції отримувача для виконання запиту
На діаграмі видно, як Command розриває зв'язок між викликачем та отримувачем (а також запитом, що повинен бути виконаний останнім).
3.5. Ланцюжок відповідальностей
Ланцюжок відповідальностей - шаблон об'єктно-орієнтованого дизайну у програмуванні.
В об'єктно-орієнтованому дизайні, шаблон «ланцюжок відповідальностей» є шаблоном, який складається з об'єктів «команда» і серії об'єктів-виконавців. Кожен об'єкт-виконавець має логіку, що описує типи об'єктів «команда», які він може обробляти, а також як передати далі ланцюжком ті об'єкти-команди, що він не може обробляти. Крім того існує механізм для додавання нових призначених для обробки об'єктів у кінець ланцюжка.
У варіаціях стандартного ланцюжка відповідальностей, деякі обробники можуть бути в ролі диспетчерів, які здатні відсилати команди в різні напрямки формуючи Дерево відподальності. У деяких випадках це можна організувати рекурсивно, коли оброблюваний обєкт викликає обєкт вищого рівня обробки з командою що пробує вирішити меншу частину проблеми; у цьому випадку рекурсія продовжує виконуватися поки команда не виконається, або поки дерево повністю не буде оброблене. XML-інтерпретатор (проаналізований, але який ще не було поставлено на виконання) може бути хорошим прикладом.
Цей шаблон застосовує ідею слабкого звязку, який розглядається як програмування у найкращих практиках.