Коротка відповідь
middleCommand — це патерн, що інкапсулює запит як об’єкт, розділяючи виклик і виконання. Кожна команда має метод execute(), а клієнт працює з інтерфейсом Command, не знаючи конкретної реалізації. Наприклад: const cmd = new TurnOnLight(); cmd.execute();
Повне пояснення
1. Що це і навіщо
Command — патерн поведінковий, що дозволяє об’єктам передавати запити іншим об’єктам без знання деталей виконання. Використовується, коли потрібна відкладена дія, черга команд, анулювання або журналування.
2. Принцип роботи / алгоритм
Клієнт створює об’єкт ConcreteCommand, який містить референс до Receiver (об’єкта‑реципієнта). ConcreteCommand реалізує інтерфейс Command і викликає методи Receiver у своєму execute(). Invoker зберігає список команд і виконує їх за потребою.
3. Реалізація (JS / TS)
- Базова реалізація
interface Command { execute(): void; }
class Light { turnOn() { console.log('Light on'); } }
class TurnOnCommand implements Command {
constructor(private light: Light) {}
execute() { this.light.turnOn(); }
}
const invoker = new TurnOnCommand(new Light());
invoker.execute();
- Веб‑dev приклад – кнопка, що виконує команду з історією
class UndoStack {
private stack: Command[] = [];
execute(cmd: Command) { cmd.execute(); this.stack.push(cmd); }
}
const stack = new UndoStack();
stack.execute(new TurnOnCommand(new Light()));
- Новачковий спрощений – прості функції
type Cmd = () => void;
const turnOn: Cmd = () => console.log('on');
turnOn();
4. Тестування (Jest або Vitest)
test('Command executes receiver method', () => {
const light = { turnOn: jest.fn() };
const cmd = new TurnOnCommand(light as any);
cmd.execute();
expect(light.turnOn).toHaveBeenCalled();
});
5. Проблеми та edge cases
- Неправильне використання ролей – інвокер викликає методи Receiver напряму, пропускаючи Command.
- Зайва абстракція – створення окремих класів для простих команд збільшує код.
- Cyclical dependencies – Command залежить від Receiver, а Receiver може зберігати команду.
- Плутанина між Command і Strategy – обидва інкапсулюють поведінку, але Command зберігає стан і історію.
- Performance‑пастки – великі черги команд можуть збільшити пам’ять і затримку.
6. Оптимізація та продуктивність
Command додає один об’єкт на команду, що збільшує пам’ять. Якщо команди прості, можна використовувати функції замість класів. Для великих систем використовуйте lazy‑loading команд або об’єкт‑pool.
7. Без JS / архітектурні альтернативи
У чистій HTML/CSS можна реалізувати «команди» через data‑атрибути і event delegation. У бекенді можна замінити Command на прості callback‑функції або Promise‑chain.
8. Cheatsheet + follow-up
- Command: інтерфейс
execute(), Receiver, Invoker. - Питання на інтерв’ю: «Як ви реалізували б команду з підтримкою анулювання?»; «Чому Command краще за простий callback у випадку черги команд?"