三分钟理解“命令模式”——设计模式轻松掌握
什么是命令模式?
假设现在有一个请求处理类(低层类/第三方类),如果客户端拿到这个类之后直接调用它,那么客户端和这个请求处理类之间的藕合度过高。
这时候我们在客户端的请求发送类和请求处理类之间增加一个Invoker类,再将请求发送类发送的所有请求封装成对象,然后让Invoker类去管理这些请求对象,并决定这些请求是否允许执行、何时执行、按什么顺序执行。
由于在请求发送类和请求处理类之间增加了请求转发者,因此这两个类之间的藕合度就大大降低。
命令模式的类图
1.Invoker类用于管理客户端想要发送的请求Command;
Invoker中有一个List<Command>,用于存放客户端发来的还没有被执行的请求;
客户端通过Invoker类中的add、delete函数,向Invoker发送或删除请求;
客户端通过Invoker类的executeCommand()函数,一次性执行Invoker中尚未被执行的请求。
2.当客户端执行Invoker的executeCommand()函数时,该函数实际调用了当前Command对象肚子中的executeCommand()函数。
Command类中含有请求处理者Receiver的对象,客户端通过Command对象中的setReceiver(Receiver)函数来设置;
当客户端调用Invoker的executeCommand()时,该函数调用了当前Command对象的executeCommand()函数,该函数再调用Command肚子中那个Receiver对象的具体处理函数。
客户端代码:
main(){
//创建Receiver对象
Receiver receiver = new Receiver();
//创建Command对象,并往Command肚子里设置该命令所要执行的处理类的对象
Command commandA = new ConcreteCommandA();
commandA.setReceiver(receiver);
Command commandB = new ConcreteCommandB();
commandB.setReceiver(receiver);
//创建Invoker对象,并往它肚子里添加需要处理的命令
Invoker invoker = new Invoker();
invoker.add(commandA);
invoker.add(commandB);
//执行Invoker肚子里的所有命令
invoker.executeCommand();
}
命令模式的优点
1.命令模式将请求发送者和请求处理者分离开,从而降低了这两个类之间的藕合;
2.通过在请求发送者和请求处理者之间增加转发类的方式,从而客户端发出的请求可以在被处理之前都存放在Invoker类的容器中,请求在被执行前就有了一个缓冲,能起到以下作用:
a)Invoker能够对客户端发出的请求进行排序;
b)Invoker能够决定是否需要驳回请求;
c)客户端可以在请求被执行前选择撤销某个请求;
d)在需要的情况下,客户端的请求可以被记录成日志;
3.增加新的命令时只需增加新的命令子类即可。
是否需要在程序设计的时候去猜测未来可能发生的事情?
不需要!敏捷开发原则告诉我们:不要为代码添加基于猜测的功能!
如果不清楚一个系统是否需要命令模式,就不要着急着去实现它;在需要的时候通过重构代码实现这个模式。
- 动态创建MySQL Group Replication的节点(r11笔记第84天)
- sysbench压测小记(r11笔记第99天)
- WordPress启用memcached动态缓存以及报错解决
- 升级CentOS6.5内核,开启Nginx的fastopen和reuseport特性
- Nginx网站使用CDN之后禁止用户真实IP访问的方法
- 相差数十倍的SQL性能分析(r11笔记第98天)
- shell脚本实现整站缓存和预缓存,进一步提升网站整体加载速度
- Oracle中的PGA监控报警分析(r11笔记第96天)
- MySQL错误修复记录:Table xx is marked as crashed and should be repaired
- WordPress百度自动推送JS优化,规避错误、重复推送问题
- Oracle 12c中DBCA搭建备库体验(r11笔记第92天)
- 一行代码彻底禁用WordPress缩略图自动裁剪功能
- MySQL中xtrabackup备份恢复全攻略(r12笔记第11天)
- 分享一次Linux任务计划crontab不执行的问题排查过程
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用picocm来进行Linux下的串口调试
- vue-drawer-layout实现手势滑出菜单栏
- iOS面试之UI大全
- 基于Ant Design Vue封装一个表单控件
- Rust闭包的虫洞穿梭
- TS 设计模式08 - 发布订阅模式
- GrowingIO 数据采集 iOS SDK 测试实践
- Kubernetes 1.19.0——Pod(2)
- 极速40分钟写出SQLite数据展示与导出功能【技术创作101训练营】
- opencv cudacodec VideoReader 报错
- Flutter中富文件标签的解决方案
- JDK 15已发布,你所要知道的都在这里!
- [Concent速成] (1) 定义和共享模块状态
- 利用JS代码批量自动取消抖音关注
- 开机报错/dev/vda1 contains a file system with errors,check forced.