命令模式是一种行为型模式。它建议将请求封装为一个独立的对象。在这个对象里包含请求相关的全部信息,因此可以将其独立执行。
在命令模式中有如下基础组件:
ReceiverReceiverCommandCommandexecute()ReceiverCommandCommandInvoker
还是通过一个具体的场景来理解下命令模式是怎样运行的。以打开电视这个行为举例,我们可以通过如下方式打开电视:
- 通过遥控器开关打开电视
- 通过电视上的开关打开电视
在这个场景中,我们有一个指令(Command)是“打开电视”,指令的接收者(Receiver)当然就是电视(TV)了,当我们执行(execute)指令时,相关指令就会让电视打开(TV.on())。
再明确下这个场景中的所有组件:
ReceiverTVCommandONTVInvokerON
ONONTV
再举个例子,想想PhotoShop这个软件,在PhotoShop中,要执行“保存”操作有三种方式:
- 从右键菜单中执行保存
- 从工具栏菜单中执行保存
- 使用Ctrl+S快捷键
Receiver
现在总结下使用命令对象的好处:
- 抽象出了潜藏的真实业务逻辑,并将其和具体的操作解耦
- 不需要为每个调用者创建不同的处理器
- 指令对象包含了执行所需的全部信息,因此它也适用于需要延迟执行的场景
看下UML类图:
InvokerInvokerInvokerReceiver
代码如下:
代码如下:
command.go(指令 interface)
type command interface {
execute()
}
device.go(Receiver interface)
type device interface {
on()
off()
}
tv.go(Receiver)
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")
}
onCommand.go(指令)
type onCommand struct {
device device
} func (c *onCommand) execute() {
c.device.on()
}
offCommand.go(指令)
type offCommand struct {
device device
} func (c *offCommand) execute() {
c.device.off()
}
button.go(Invoker,开关打开电视)
type button struct {
command command
} func (b *button) press() {
b.command.execute()
}
main.go(Client)
func main() { tv := &tv{}
onCommand := &onCommand{
device: tv,
} offCommand := &offCommand{
device: tv,
} onButton := &button{
command: onCommand,
} onButton.press() offButton := &button{
command: offCommand,
}
offButton.press()
}
运行结果:
Turning tv on
Turning tv off
代码已上传至GitHub:github / zhyea / command
END!