
Команда на 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