命令模式是一种行为设计模式,它可将请求转换为一个包含与请求相关的所有信息的独立对象。该转换让你能根据不同的请求将方法参数化、延迟请求执行或将其放入队列中,且能实现可撤销操作。
解决什么问题?
- 如果你需要通过操作来参数化对象,可使用命令模式。
- 如果你想要将操作放入队列中、操作的执行或者远程执行操作,可使用命令模式。
- 如果你想要实现操作回滚功能,可使用命令模式。
优势:
- 单一职责原则。 你可以解耦触发和执行操作的类。
- 开闭原则。 你可以在不修改已有客户端代码的情况下在程序中创建新的命令。
- 你可以实现撤销和恢复功能。
- 你可以实现操作的延迟执行。
- 你可以将一组简单命令组合成一个复杂命令
劣势:
- 代码可能会变得更加复杂,因为你在发送者和接收者之间增加了一个全新的层次。
实现步骤:
- 定义
命令接口 具体命令类实现命令接口,具体命令类关联接收者类- 定义
接收者类,该类执行具体的操作 - 定义
发送者类,将该类与具体命令类关联,通过具体命令类调用接收者类的执行函数 - 客户端关联
具体命令类、发送者类和接收者类
下面是实现代码:
package main
import "fmt"
type command interface {
execute()
}
type drawCmd struct {
r *receiver
params int
}
func newDrawCmd(r *receiver, params int) *drawCmd {
return &drawCmd{
r: r,
params: params,
}
}
func (d *drawCmd) execute() {
d.r.operation(d.params)
}
type moveCmd struct {
r *receiver
params int
}
func newMoveCmd(r *receiver, params int) *moveCmd {
return &moveCmd{
r: r,
params: params,
}
}
func (m *moveCmd) execute() {
m.r.operation(m.params)
}
type sender struct {
c command
}
func newSender(c command) *sender {
return &sender{c: c}
}
func (s *sender) setCmd(c command) {
s.c = c
}
func (s *sender) executeCmd() {
s.c.execute()
}
type receiver struct{}
func (r *receiver) operation(params int) {
fmt.Println("do something with params:", params)
}
func main() {
r := &receiver{}
dc := newDrawCmd(r, 1)
s := newSender(dc)
s.executeCmd() // do something with params: 1
mc := newMoveCmd(r, 2) // do something with params: 2
s.setCmd(mc)
s.executeCmd()
}