命令模式的使用频率低,理解难度比较大,只有在特定的应用场景会才会用到。
1. 命令模式的原理
命令模式(Command Design Pattern):命令模式将请求(命令)封装为一个对象,这样可以使用不同的请求参数化其他对象(将不同请求依赖注入到其他对象),并且能够支持请求(命令)的排队执行、记录日志、撤销等(附加控制)功能。
The command pattern encapsulates a request as an object, thereby letting us parameterize other objects with different requests, queue or log requests, and support undoable operations.
落实到编码实现,命令模式用的最核心的实现手段,是将函数封装成对象。Golang 天生支持函数指针,将函数当作变量传递来传递去。具体来说就是,设计一个包含这个函数的类,实例化一个对象传来传去,这样就可以实现把函数像对象一样使用。从实现的角度来说,它类似回调。
把函数封装成对象之后,对象就可以存储下来,方便控制执行。所以,命令模式的主要作用和应用场景,是用来控制命令的执行,比如,异步、延迟、排队执行命令、撤销重做命令、存储命令、给命令记录日志等等,这才是命令模式能发挥独一无二作用的地方。
2. 命令模式的代码实现
type device interface {
on()
off()
}
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")
}
type command interface {
execute()
}
type onCommand struct {
device device
}
func (o *onCommand) execute() {
o.device.on()
}
type offCommand struct {
device device
}
func (o *offCommand) execute() {
o.device.off()
}
type button struct {
command command
}
func (b *button) press() {
b.command.execute()
}
// 客户端使用代码
func TestCommand(t *testing.T) {
tv := &tv{}
onCommand := &onCommand{
device: tv,
}
offCommand := &offCommand{
device: tv,
}
onButton := &button{
command: onCommand,
}
onButton.press()
offButton := &button{
command: offCommand,
}
offButton.press()
}