命令模式

类图

代码

Command

1
2
3
4
interface Command{
void execute();
void undo();
}

Receiver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Receiver{

void action1(){
System.out.println("执行操作1");
}

void undo1(){
System.out.println("撤销操作1");
}

void action2(){
System.out.println("执行操作2");
}

void undo2(){
System.out.println("撤销操作2");
}
}

ConcreteCommand

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 播放命令
*/
class PlayCommand implements Command{

private Receiver receiver;

public PlayCommand(Receiver receiver) {
this.receiver = receiver;
}

@Override
public void execute() {
receiver.action1();
}

@Override
public void undo() {
receiver.undo1();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 停止命令
*/
class StopCommand implements Command{

private Receiver receiver;

public StopCommand(Receiver receiver) {
this.receiver = receiver;
}

@Override
public void execute() {
receiver.action2();
}

@Override
public void undo() {
receiver.undo2();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class MarcoCommand implements Command{

private List<Command> commands = new ArrayList<>();

public void add(Command command){
this.commands.add(command);
}

public void remove(Command command){
this.commands.remove(command);
}

@Override
public void execute() {
for (Command command : commands) {
command.execute();
}
}

@Override
public void undo() {
for (Command command : commands) {
command.undo();
}
}
}

Invoker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Invoker{

private Command command;

private List<Command> undoList = new ArrayList<>();
private List<Command> redoList = new ArrayList<>();

public Invoker(Command command) {
this.command = command;
}

public void action(){
this.undoList.add(command);
command.execute();
}

public void undo(){
if(this.undoList.size() <= 0){
return;
}

command.undo();

this.undoList.remove(command);
this.redoList.add(command);
}

public void redo(){
if(this.redoList.size() <= 0){
return;
}

command.execute();

this.redoList.remove(command);
this.undoList.add(command);
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Main {
public static void main(String args[]){
Receiver receiver = new Receiver();

Command playCommand = new PlayCommand(receiver);
Command stopCommand = new StopCommand(receiver);
MarcoCommand macroCommand = new MarcoCommand();

macroCommand.add(playCommand);
macroCommand.add(stopCommand);

Invoker invoker = new Invoker(playCommand);

invoker.action();
invoker.undo();
invoker.redo();
invoker.redo();

System.out.println("----------------------------");

invoker = new Invoker(macroCommand);

invoker.action();
invoker.undo();
invoker.redo();
invoker.redo();

}
}

运行结果

1
2
3
4
5
6
7
8
9
10
执行操作1
撤销操作1
执行操作1
----------------------------
执行操作1
执行操作2
撤销操作1
撤销操作2
执行操作1
执行操作2

总结

概述

Receiver实际上就是操作实体

Command就是操作执行的封装,抽象为命令,基于此可以实现宏命令,例子中MacroCommand的实现

Invoker实际上就是一个操作者,它可以用来做一些command操作记录,以达到撤销、重做操作

优点

命令模式通过把实际操作进行封装,通过操作者,可以很方便的实现一些重做、队列化、日志化等操作,从而使得系统更加灵活

对于宏操作、撤销、重试等一些系统的基础功能都是使用命令模式完成的

缺点