
Команда на Go
Команда — це поведінковий патерн, що дозволяє загортати запити або прості операції в окремі об’єкти.
Це дозволяє відкладати виконання команд, вибудовувати їх у чергу, а також зберігати історію і робити скасування.
Концептуальний приклад
Давайте розглянемо патерн Команда на прикладі телевізора. ТV може бути увімкнено двома способами:
- кнопка УВІМК на пульті дистанційного керування;
- кнопка ВИМК на самому телевізорі.
Ми можемо почати з реалізації об’єкта команди УВІМК з телевізором у ролі одержувача. Коли на цю команду викликається метод execute
, вона, у свою чергу, викликає функцію TV.on
. Вищевказане визначає об’єкт виклику. Насправді ми матимемо два об’єкта виклику: пульт і сам ТВ. Обидва будуть містити об’єкт команди ВКЛ.
Зауважте, що ми обернули один і той же запит в кілька об’єкті виклику. Це ж саме можна робити і з іншими командами. Перевагою створення окремих об’єктів команд є відділення логіки користувацького інтерфейсу від внутрішньої бізнес-логіки. Немає потреби розробляти окремих виконавців для кожного об’єкта виклику — сама команда містить всю інформацію, необхідну для її виконання. Відповідно, її можна використовувати для відстроченого виконання завдання.
button.go: Відправник
package main type Button struct { command Command } func (b *Button) press() { b.command.execute() }
command.go: Інтерфейс команд
package main type Command interface { execute() }
onCommand.go: Конкретна команда
package main type OnCommand struct { device Device } func (c *OnCommand) execute() { c.device.on() }
offCommand.go: Конкретна команда
package main type OffCommand struct { device Device } func (c *OffCommand) execute() { c.device.off() }
device.go: Інтерфейс отримувача
package main type Device interface { on() off() }
tv.go: Конкретний отримувач
package main import "fmt" type Tv struct { isRunning bool } func (t *Tv) on() { t.isRunning = true fmt.Println("Turning tv on") } func (t *Tv) off() { t.isRunning = false fmt.Println("Turning tv off") }
main.go: Клієнтський код
package main func main() { tv := &Tv{} onCommand := &OnCommand{ device: tv, } offCommand := &OffCommand{ device: tv, } onButton := &Button{ command: onCommand, } onButton.press() offButton := &Button{ command: offCommand, } offButton.press() }
output.txt: Результат виконання
Turning tv on Turning tv off