![Команда](/images/patterns/cards/command-mini.png?id=b149eda017c0583c1e92343b83cfb1eb)
Команда на 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