博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家
Java知识图谱点击链接:体系化学习Java(Java面试专题)
感兴趣的同学可以收藏关注下 ,不然下次找不到哟
命令模式是一种行为设计模式,它将请求封装成一个对象,从而允许我们根据不同的请求将客户端参数化,将请求排入队列或记录请求日志,并支持可撤销的操作。
命令模式的优点包括:
解耦合:命令模式可以将发送者和接收者解耦,发送者不需要知道接收者的具体实现细节,只需通过命令对象来发送请求。
可扩展性:通过添加新的具体命令类,可以很容易地扩展命令模式,而无需修改已有的代码,符合开闭原则。
可以实现撤销和重做:命令模式可以记录命令的执行历史,从而支持撤销和重做操作。
支持事务性操作:命令模式可以将多个命令组合成一个复合命令,从而实现事务性操作,确保多个命令的执行和撤销都成功。
可以实现日志和审计功能:由于命令模式记录了命令的执行历史,可以用于实现日志和审计功能。
命令模式的缺点包括:
代码复杂性增加:引入命令对象和调用者对象,会增加代码的复杂性和额外的类。
可能会导致类爆炸:如果系统中有大量的命令类,可能会导致类的数量爆炸,增加系统的复杂性。
执行效率降低:由于命令模式需要将请求封装成对象,可能会导致执行效率降低。
综上所述,命令模式在需要将请求发送者和接收者解耦、支持撤销和重做、实现事务性操作等场景下非常有用。但在一些简单的场景下,引入命令模式可能会增加代码复杂性,因此需要根据具体情况进行权衡和选择。
命令模式适用于以下场景:
需要解耦发送者和接收者:当需要将请求发送者和接收者解耦,使得发送者不需要知道接收者的具体实现细节时,可以使用命令模式。
支持撤销和重做操作:命令模式可以记录命令的执行历史,从而支持撤销和重做操作。例如,在文本编辑器中,可以使用命令模式实现对文本的撤销和重做操作。
实现事务性操作:命令模式可以将多个命令组合成一个复合命令,从而实现事务性操作。例如,在数据库操作中,可以使用命令模式将多个数据库操作封装成一个事务命令,保证多个操作的执行和撤销都成功。
实现日志和审计功能:由于命令模式记录了命令的执行历史,可以用于实现日志和审计功能。例如,在系统中记录用户操作日志或审计操作。
需要支持命令的延迟执行或异步执行:命令模式可以将命令对象存储起来,延迟执行或异步执行。例如,在任务调度系统中,可以使用命令模式将任务封装成命令对象,然后由调度器定时执行。
总之,命令模式适用于需要将请求发送者和接收者解耦、支持撤销和重做、实现事务性操作、实现日志和审计功能,以及支持命令的延迟执行或异步执行的场景。
命令模式的结构包括以下几个主要角色:
命令接口(Command Interface):定义了执行命令的方法,通常包括一个execute()方法。所有具体命令类都要实现该接口。
具体命令(Concrete Command):实现了命令接口,负责执行具体的操作。它包含了接收者对象,并调用接收者的方法来完成命令的执行。
接收者(Receiver):执行具体操作的对象。命令模式将命令和接收者解耦,使得命令对象不需要了解接收者的具体实现。
调用者(Invoker):负责调用命令对象来执行请求。它持有一个命令对象,并在需要执行命令时调用命令的execute()方法。
客户端(Client):创建具体命令对象并设置其接收者,然后将命令对象传递给调用者来执行。
命令模式的工作原理如下:
客户端创建具体命令对象,并设置其接收者。具体命令对象实现了命令接口,其中包含了执行具体操作的逻辑,并持有一个接收者对象的引用。
客户端将命令对象传递给调用者。调用者是命令的执行者,它持有命令对象,并在需要执行命令的时候调用命令的execute()方法。
调用者调用命令对象的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 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
本文由激流原创,首发于程序员宅基地,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
喜欢的话记得点赞收藏啊
文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib
文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang
文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些
文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器
文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距
文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器
文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn
文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios
文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql
文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...
文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120
文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数