命令模式
命令模式
命令模式
什么是命令模式?
命令模式的定义
Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations.(将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。)
命令模式的核心在于引入了命令类,通过命令类来降低发送者和接收者的耦合度,请求发送者只需指定一个命令对象,再通过命令对象来调用请求接收者的处理方法。
命令模式通用类图
命令模式包含这么几个角色:
- Command(抽象命令):声明需要执行的命令
- ConcreteCommand(具体的命令,可能有多个):实现声明的命令
- Receive(接收者,具体业务实现者):接收者执行与请求相关的操作,它具体实现对请求的业务处理
- Invoker(调用者):调用者即请求发送者,它通过命令对象来执行请求。
命令模式的本质是对请求进行封装,一个请求对应于一个命令,将发出命令的责任和执行命令的责任分割开。每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行相应的操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求如何被接收、操作是否被执行、何时被执行,以及是怎么被执行的。
案例
案例 1
- Receiver:Receiver 类实现具体的业务需求
1
2
3
4
5
6
7
8
9
/**
* Receiver类实现具体的业务需求
*/
public class Receiver {
public void doSomething() {
// 具体的业务逻辑
System.out.println("Receiver类实现具体的业务需求");
}
}
- 接口的 Command 类定义命令:
1
2
3
4
5
6
7
/**
* 命令接口
*/
public interface Command {
// 每个命令类都必须有一个执行命令的方法
void execute();
}
- 具体的 Command 类:根据需求,具体的命令类可以有多个:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 具体的Command类:根据需求,具体的命令类可以有多个
*/
public class ConcreteCommand1 implements Command {
// 维持一个对请求接收者对象的引用
private Receiver receiver;
// 构造函数传递接收者
public ConcreteCommand1(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
// 调用请求接收者的业务处理方法doSomething()
receiver.doSomething();
}
}
- 调用者 Invoker 类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 调用者Invoker类
*/
public class Invoker {
private Command command;
// 设值注入
public void setCommand(Command command) {
this.command = command;
}
// 执行命令
public void action() {
this.command.execute();
}
}
- 场景类:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Client {
public static void main(String[] args) {
// 首先声明调用者Invoker
Invoker invoker = new Invoker();
// 定义接收者
Receiver receiver = new Receiver();
// 定义一个发送给接收者的命令
Command command = new ConcreteCommand1(receiver);
// 把命令交给调用者去执行
invoker.setCommand(command);
invoker.action();
}
}
命令模式使用场景
- 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。请求调用者 无须知道接收者的存在,也无须知道接收者是谁,接收者也无须关心何时被调用。
- 系统需要在不同的时间指定请求、将请求排队和执行请求。一个命令对象和请求的初始调 用者可以有不同的生命期,换言之,最初的请求发出者可能已经不在了,而命令对象本身仍 然是活动的,可以通过该命令对象去调用请求接收者,而无须关心请求调用者的存在性,可以通过请求日志文件等机制来具体实现。
- 系统需要支持命令的撤销 (Undo) 操作和恢复 (Redo) 操作。
Ref
- 设计模式—— 十五 :命令模式
https://juejin.cn/post/6844904177399775245
本文由作者按照 CC BY 4.0 进行授权