命令(Command)模式
# 命令(Command)模式
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
命令模式包含以下主要角色。
- 抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute ()。
- 具体命令类(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
- 实现者 / 接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
- 调用者 / 请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。

抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute ()。
/**
* 抽象命令类
* Controller、service、dao接口
*/
public interface Command {
/**
* 命令的执行方法
*/
void execute();
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
具体命令类(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
public class OnlineCommand implements Command{
//dao
private LeiReceiver leiReceiver = new LeiReceiver();
@Override
public void execute() {
System.out.println("要上课了");
leiReceiver.online();
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
public class WuHanTravelCommand implements Command {
private LeiReceiver leiReceiver = new LeiReceiver();
@Override
public void execute() {
System.out.println("要去武汉出差了");
leiReceiver.travel();
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
实现者 / 接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
public class LeiReceiver {
public void online(){
System.out.println("在课堂中");
}
public void travel(){
System.out.println("在出差中");
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
调用者 / 请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
/**
* controller
*/
public class TeacherTongInvoker {
Command command;
public void call() {
// 命令的执行
command.execute();
}
public void setCommand(Command command) {
this.command = command;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
测试
public class MainTest {
public static void main(String[] args) {
TeacherTongInvoker invoker = new TeacherTongInvoker();
invoker.setCommand(new WuHanTravelCommand());
invoker.call();
invoker.setCommand(new OnlineCommand());
invoker.call();
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 应用场景
什么场景用到?
- mvc 就是典型的命令模式
- 当系统需要执行一组操作时,命令模式可以定义宏命令(一个命令组合了多个命令)来实现该功能。
- 结合备忘录模式还可以实现命令的撤销和恢复
Spring 框架的 JdbcTemplate 就使用到了命令模式

- StatementCallback 接口,类似命令接口 (Command)
- class QueryStatementCallback implements StatementCallback
<T>, SqlProvider , 匿名内部类, 实现了命令接口,同时也充当命令接收者 - 命令调用者是 JdbcTemplate , 其中 execute (StatementCallback
<T>action) 方法中,调用 action.doInStatement 方法。不同的 实现 StatementCallback 接口的对象,对应不同的 doInStatemnt 实现逻辑 - 另外实现 StatementCallback 命令接口的子类还有 QueryStatementCallback、

# 注意事项和细节
- 将发起请求的对象与执行请求的对象解耦。发起请求的对象是调用者,调用者只要调用命令对象的 execute () 方法就可以让接收者工作,而不必知道具体的接收者对象是谁、是如何实现的,命令对象会负责让接收者执行请求的动作,也就是说:” 请求发起者” 和 “请求执行者” 之间的解耦是通过命令对象实现的,命令对象起到了纽带桥梁的作用。
- 容易设计一个命令队列。只要把命令对象放到列队,就可以多线程的执行命令
- 容易实现对请求的撤销和重做
- 命令模式不足:可能导致某些系统有过多的具体命令类,增加了系统的复杂度,这点在在使用的时候要注意
- 空命令也是一种设计模式,它为我们 省去了判空的操作。在上面的实例中,如果没有用空命令,我们每按一个按键都要判空,这给我们编码带来一定的麻烦。
- 命令模式经典的应用场景:界面的一个按钮都是一条命令、模拟 CMD(DOS 命令)订单的撤销 / 恢复、触发 - 反馈机制
编辑 (opens new window)
上次更新: 2023/12/13, 06:06:02