博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌
Java知识图谱点击链接:体系化学习Java(Java面试专题)
💕💕 感兴趣的同学可以收藏关注下 ,不然下次找不到哟💕💕
1、什么是命令模式
命令模式是一种行为设计模式,它将请求封装成一个对象,从而允许我们根据不同的请求将客户端参数化,将请求排入队列或记录请求日志,并支持可撤销的操作。
2、命令模式的优缺点
命令模式的优点包括:
解耦合:命令模式可以将发送者和接收者解耦,发送者不需要知道接收者的具体实现细节,只需通过命令对象来发送请求。
可扩展性:通过添加新的具体命令类,可以很容易地扩展命令模式,而无需修改已有的代码,符合开闭原则。
可以实现撤销和重做:命令模式可以记录命令的执行历史,从而支持撤销和重做操作。
支持事务性操作:命令模式可以将多个命令组合成一个复合命令,从而实现事务性操作,确保多个命令的执行和撤销都成功。
可以实现日志和审计功能:由于命令模式记录了命令的执行历史,可以用于实现日志和审计功能。
命令模式的缺点包括:
代码复杂性增加:引入命令对象和调用者对象,会增加代码的复杂性和额外的类。
可能会导致类爆炸:如果系统中有大量的命令类,可能会导致类的数量爆炸,增加系统的复杂性。
执行效率降低:由于命令模式需要将请求封装成对象,可能会导致执行效率降低。
综上所述,命令模式在需要将请求发送者和接收者解耦、支持撤销和重做、实现事务性操作等场景下非常有用。但在一些简单的场景下,引入命令模式可能会增加代码复杂性,因此需要根据具体情况进行权衡和选择。
3、命令模式的应用场景
命令模式适用于以下场景:
需要解耦发送者和接收者:当需要将请求发送者和接收者解耦,使得发送者不需要知道接收者的具体实现细节时,可以使用命令模式。
支持撤销和重做操作:命令模式可以记录命令的执行历史,从而支持撤销和重做操作。例如,在文本编辑器中,可以使用命令模式实现对文本的撤销和重做操作。
实现事务性操作:命令模式可以将多个命令组合成一个复合命令,从而实现事务性操作。例如,在数据库操作中,可以使用命令模式将多个数据库操作封装成一个事务命令,保证多个操作的执行和撤销都成功。
实现日志和审计功能:由于命令模式记录了命令的执行历史,可以用于实现日志和审计功能。例如,在系统中记录用户操作日志或审计操作。
需要支持命令的延迟执行或异步执行:命令模式可以将命令对象存储起来,延迟执行或异步执行。例如,在任务调度系统中,可以使用命令模式将任务封装成命令对象,然后由调度器定时执行。
总之,命令模式适用于需要将请求发送者和接收者解耦、支持撤销和重做、实现事务性操作、实现日志和审计功能,以及支持命令的延迟执行或异步执行的场景。
4、命令模式的结构
命令模式的结构包括以下几个主要角色:
命令接口(Command Interface):定义了执行命令的方法,通常包括一个execute()方法。所有具体命令类都要实现该接口。
具体命令(Concrete Command):实现了命令接口,负责执行具体的操作。它包含了接收者对象,并调用接收者的方法来完成命令的执行。
接收者(Receiver):执行具体操作的对象。命令模式将命令和接收者解耦,使得命令对象不需要了解接收者的具体实现。
调用者(Invoker):负责调用命令对象来执行请求。它持有一个命令对象,并在需要执行命令时调用命令的execute()方法。
客户端(Client):创建具体命令对象并设置其接收者,然后将命令对象传递给调用者来执行。
5、命令模式的工作原理
命令模式的工作原理如下:
客户端创建具体命令对象,并设置其接收者。具体命令对象实现了命令接口,其中包含了执行具体操作的逻辑,并持有一个接收者对象的引用。
客户端将命令对象传递给调用者。调用者是命令的执行者,它持有命令对象,并在需要执行命令的时候调用命令的execute()方法。
调用者调用命令对象的execute()方法。这个方法会调用接收者对象的相应方法来执行具体操作。
接收者执行具体操作。接收者是命令的实际执行者,它负责执行具体的操作逻辑。
通过命令模式,发送者和接收者之间解耦,发送者只需要知道如何调用命令对象,而不需要知道具体的接收者和操作。这样可以更灵活地组织和管理命令,并支持撤销、重做、事务、日志等功能。
命令模式的核心思想是将请求封装成对象,从而使得请求的发送者和接收者解耦,并且可以方便地扩展和修改命令。它适用于需要将请求封装成独立对象,并且支持撤销、重做、事务等操作的场景。
6、命令模式的代码案例
以下是一个简单的命令模式的代码案例:
package com.pany.camp.design.principle.command;
/**
*
* @description: 接口
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 12:26
*/
public interface Command {
void execute();
}
定义接收者类
package com.pany.camp.design.principle.command;
/**
*
* @description: 定义接收者类
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 12:26
*/
public class Receiver {
public void action() {
System.out.println("执行具体操作");
}
}
定义具体命令类,实现命令接口
package com.pany.camp.design.principle.command;
/**
*
* @description: 定义具体命令类,实现命令接口
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 12:26
*/
public class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
public void execute() {
receiver.action();
}
}
定义调用者类
package com.pany.camp.design.principle.command;
/**
*
* @description: 调用者类
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 12:29
*/
public class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
command.execute();
}
}
客户端代码如下:
package com.pany.camp.design.principle.command;
/**
*
* @description: 客户端
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 12:27
*/
public class Client {
public static void main(String[] args) {
// 创建接收者对象
Receiver receiver = new Receiver();
// 创建具体命令对象,并设置接收者
Command command = new ConcreteCommand(receiver);
// 创建调用者对象,并设置具体命令
Invoker invoker = new Invoker();
invoker.setCommand(command);
// 调用者执行命令
invoker.executeCommand();
}
}
Command接口定义了命令的执行方法execute()。具体命令类ConcreteCommand实现了Command接口,并持有一个接收者对象的引用,在execute()方法中调用接收者的action()方法来执行具体操作。接收者类Receiver定义了具体操作的逻辑。调用者类Invoker持有一个命令对象,并提供了设置命令和执行命令的方法。在客户端代码中,创建接收者对象、具体命令对象和调用者对象,并通过调用者对象来执行命令。
输出如下:
执行具体操作
Process finished with exit code 0
💕💕 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
💕💕喜欢的话记得点赞收藏啊