命令模式(Command Pattern)将请求或操作封装为一个对象,从而允许使用不同的请求、队列或日志来参数化其他对象。在这种模式下,命令的调用者与接收者之间解耦,使得调用者不需要知道接收者的具体实现
逻辑结构
在命令模式中,涉及以下几个核心角色:
- 命令(Command):命令对象封装了执行特定操作的方法,并在需要时将该操作的接收者(执行者)绑定到命令对象上。
- 接收者(Receiver):接收者是命令的实际执行者,负责执行命令所代表的操作。
- 调用者(Invoker):调用者负责调用命令对象并触发执行相应的操作。它并不直接知道命令的具体细节,只需知道如何触发命令的执行。
- 客户端(Client):客户端创建具体的命令对象,并将命令对象与相应的接收者进行绑定。客户端负责组装命令对象和接收者,并决定命令的执行时间和顺序。

实现代码
代码路径:https://github.com/XBoom/DesignPatterns/tree/main/22_Command
-
首先,定义命令接口,封装执行特定操作的方法
1
2
3
4// Command 接口定义了命令对象的执行方法
type Command interface {
Execute()
} -
然后,定义接受接口,命令的实际执行者
1
2
3
4// Receiver 接收者接口
type Receiver interface {
Action()
} -
接着,定义具体的接受者
1
2
3
4
5
6// ConcreteReceiver 具体接收者
type ConcreteReceiver struct{}
func (cr *ConcreteReceiver) Action() {
fmt.Println("接收者执行具体操作")
} -
然后,定义具体命令,将接受者绑定到命令,并进行执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14// ConcreteCommand 具体命令
type ConcreteCommand struct {
receiver Receiver
}
func NewConcreteCommand(receiver Receiver) *ConcreteCommand {
return &ConcreteCommand{
receiver: receiver,
}
}
func (cc *ConcreteCommand) Execute() {
cc.receiver.Action()
} -
最后,定义调用者负责命令执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// Invoker 调用者
type Invoker struct {
command Command
}
func NewInvoker(command Command) *Invoker {
return &Invoker{
command: command,
}
}
func (i *Invoker) SetCommand(command Command) {
i.command = command
}
func (i *Invoker) ExecuteCommand() {
i.command.Execute()
}
运行
1 | //1. 命令接受者 |
结果
1 | 接收者执行具体操作 |
适用场景
- 菜单和按钮操作:在图形用户界面中,菜单和按钮通常需要与不同的操作关联。使用命令模式,可以将每个操作封装成一个命令对象,然后在菜单和按钮上设置相应的命令,使得菜单和按钮可以触发执行不同的操作。
- 撤销和重做:命令模式非常适合实现撤销和重做功能。通过将每个操作封装成一个命令对象,并将命令对象的历史记录保存下来,可以轻松地实现撤销和重做操作,只需按照命令历史记录依次执行即可。
- 任务调度和队列处理:命令模式可以用于实现任务调度和队列处理。将每个任务封装成一个命令对象,并将命令对象放入任务队列中,调度器可以按照队列的顺序依次执行命令,从而实现任务的调度和顺序处理。
- 日志记录:命令模式可以用于实现日志记录功能。将每个操作封装成一个命令对象,并在执行命令时记录相关的日志信息,可以方便地实现对操作的日志记录和分析。
- 事务处理:命令模式可以用于实现事务处理功能。将一系列操作封装成多个命令对象,并在执行命令时进行事务的提交或回滚,从而实现对事务的管理和控制
总的来说,命令模式适用于需要将请求发送者和请求接收者解耦的场景,以及需要支持撤销、重做、任务调度、日志记录和事务处理等功能的场景。通过将操作封装成命令对象,可以使得系统更灵活、可扩展,并提供更好的代码结构和可维护性
总结
- 单一职责原则。 可以解耦触发和执行操作的类
- 开闭原则。 可以在不修改已有客户端代码的情况下在程序中创建新的命令
- 可以实现撤销和恢复功能
- 可以实现操作的延迟执行
- 可以将一组简单命令组合成一个复杂命令