命令模式
# 命令模式
# 定义
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个独立的对象,从而使发送者和接收者解耦。
# 结构
命令(Command): 定义了执行操作的接口,通常包含一个执行方法 execute()。
具体命令(Concrete Command): 实现了命令接口,持有一个接收者对象,并在执行方法中调用接收者的具体操作。
接收者(Receiver): 执行具体操作的对象。命令模式将请求封装到接收者对象中,并由接收者执行实际的操作。
调用者(Invoker): 发送命令的对象,持有命令对象,并在需要执行命令的时候调用命令的执行方法。
客户端(Client): 创建命令对象、接收者对象和调用者对象,并进行配置和组合。客户端将命令和接收者进行连接,并可以控制命令的执行。
- img: https://bitouyun.com/images/design-pattern/command.png
link: https://bitouyun.com/images/design-pattern/command.png
name: 命令模式
2
3
# 优点
松耦合:命令模式将请求发送者和请求接收者解耦,使得它们之间不直接依赖于具体的实现。发送者只需要知道如何发送命令,而不需要知道如何执行命令,从而降低了对象之间的耦合性。
可扩展性:命令模式支持新的命令类的添加,而无需修改现有的代码。通过添加新的具体命令类,可以方便地扩展系统的功能。
容易实现撤销和重做:由于命令模式将每个命令封装为一个对象,可以轻松地实现撤销和重做的功能。通过记录命令的历史操作,可以方便地撤销一系列命令,或者重新执行已经撤销的命令。
支持命令的队列化和延迟执行:命令模式可以将命令对象存储在队列中,支持对命令的队列化和延迟执行。这样可以灵活地控制命令的执行顺序和时间。
# 缺点
增加系统的复杂性:在复杂的场景下,可能需要创建大量的具体命令类,从而增加了系统的复杂性。
增加了类和对象数量:引入了命令对象和调用者对象,增加了系统中类和对象的数量。这可能会增加内存消耗和系统的复杂性。
# 应用场景
解耦:当发送者和接收者之间的关系需要解耦时,可以使用命令模式。这样可以使得发送者和接收者之间的交互更灵活、可扩展。
支持撤销、重做、队列化和延迟执行:命令模式可以方便地实现撤销、重做等功能,以及支持命令的队列化和延迟执行。这在需要对操作进行管理和控制的场景下非常有用。
将一系列操作封装成一个命令:当需要将一系列操作封装起来,并作为一个单元进行执行时,可以使用命令模式。这样可以更方便地管理和执行复杂的操作序列。
支持扩展和变化:命令模式可以方便地扩展和变化。通过添加新的具体命令类,可以增加系统的功能,而不需要修改现有的代码。
# 示例代码
场景
餐厅点餐例子,服务员Waiter是调用者,厨师Chef是接收者,顾客Customer点菜后,服务员将顾客的需求封装成一个命令对象OrderCommand传递给厨师,厨师根据命令完成烹饪工作。
/**
* 点餐命令接口
* 抽象命令接口,定义执行操作的统一方法
*/
public interface Command {
// 点餐
void order();
// 取消点餐
void cancelOrder();
}
2
3
4
5
6
7
8
9
10
11
/**
* 点餐命令
* 具体命令类,持有接收者引用,通过调用接收者的方法执行操作。
*/
public class OrderCommand implements Command {
// 持有接收者对象
private Chef chef;
public OrderCommand(Chef chef) {
this.chef = chef;
}
// 执行点菜操作
@Override
public void order() {
chef.cook();
}
@Override
public void cancelOrder() {
chef.cancelCook();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 厨师
* 接收者,实际执行命令的类。通过命令接口调用接收者的方法执行。
*/
@Slf4j
public class Chef {
// 烹饪
public void cook() {
log.info("厨师执行点菜命令:正在烹饪菜品......");
}
// 取消烹饪
public void cancelCook() {
log.info("初始执行取消命令:停止烹饪菜品......");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 服务员
* 调用者,持有命令对象,不直接访问接收者,通过命令接口执行操作。
*/
public class Waiter {
// 命令接口
private Command command;
public void setCommand(Command command) {
this.command = command;
}
// 点餐
public void order() {
// 服务员接收到顾客点菜请求,执行点菜操作
command.order();
}
// 取消点餐
public void cancelOrder() {
// 服务员收到顾客取消点菜请求
command.cancelOrder();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 测试类
*/
public class Client {
public static void main(String[] args) {
// 接收者
Chef chef = new Chef();
// 点菜命令
Command command = new OrderCommand(chef);
// 调用者
Waiter waiter = new Waiter();
// 设置命令
waiter.setCommand(command);
waiter.order(); // 点菜
waiter.cancelOrder(); // 取消点菜
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Make sure to add code blocks to your code group