命令模式

​ 将一个请求封装为对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。也称为:动作(Action)模式、事务(transaction)模式。

模式结构

  • Command抽象命令类: 声明执行操作的接口。
  • ConcreteComand具体命令类:通常持有 一个接收者对象并绑定于一个动作, 调用接收者相应的操作,以实现execute方法。
  • Invoker调用者/请求者: 请求的发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联。在程序运行时,将调用命令对象的execute(),间接调用接收者的相关操作。
  • Receiver接收者:接收者执行与请求相关的操作,具体实现对请求的业务处理。

结构图

图1

代码

Receiver接收者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package designMode.command;

/**
* 真正的命令执行者
*
* @author YoungDream
* @since 2019/4/17 12:30
*/
public class Receiver {
//批准执行
public void approve() {
System.out.println("Receiver...approve方法...");
}

//禁止执行
public void prohibit() {
System.out.println("Receiver...prohibit方法...");
}
}

Command抽象命令类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package designMode.command;

/**
* 抽象的命令接口
*
* @author YoungDream
* @since 2019/4/17 12:33
*/
public interface Command {
//执行
void execute();

//撤销
void cancel();
}

ConcreteComand具体命令类

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
package designMode.command;

/**
* 具体的命令类
*
* @author YoungDream
* @since 2019/4/17 12:38
*/
public class ConcreteCommand implements Command {
private Receiver receiver;

public ConcreteCommand(Receiver receiver) {
super();
this.receiver = receiver;
}

@Override
public void execute() {
//添加执行命令之前的操作

receiver.approve();//执行命令

//添加执行命令之后的操作
}

@Override
public void cancel() {
receiver.prohibit();//禁止执行
}
}

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
package designMode.command;

/**
* 调用类
*
* @author YoungDream
* @since 2019/4/17 12:43
*/
public class Invoker {
private Command command;

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

//执行命令
public void runCommand() {
command.execute();
}

//取消命令
public void cancelCommand() {
command.cancel();
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package designMode.command;

/**
* @author YoungDream
* @since 2019/4/17 12:45
*/
public class Client {
public static void main(String[] args) {
//创建接收者
Receiver receiver = new Receiver();
//创建命令对象,并设置接收者
Command command = new ConcreteCommand(receiver);

//创建调用者,设置命令
Invoker invoker = new Invoker(command);

invoker.runCommand();
invoker.cancelCommand();
}
}

控制台

1
2
Receiver...approve方法...
Receiver...prohibit方法...

优缺点

优点

  • 降低对象之间的耦合度。
  • 新的命令可以很容易地加入到系统中。
  • 可以比较容易地设计一个组合命令。
  • 调用同一方法实现不同的功能。

缺点

  • 使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

总结

  • 命令模式将发出请求的对象和执行请求的对象解耦, 在被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者和一个或一组动作。
  • 命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
  • 命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。