简介
命令模式(Command Pattern):将请求封装为对象,从而可用不同的请求对客户进行参数化,对请求排队或者记录请求日志,支持可撤销的操作。
- 将发送者的请求封装在命令对象中,再通过命令对象调用接受者的方法。也称动作模式和事务模式。
- 允许请求的一方和接收的一方独立开。
结构和实现
- 角色包括:
- 抽象命令类:声明用于执行请求的excute方法。
- 具体命令类:实现抽象命令类,持有接受者对象,调用接受者对象的相关操作。
- 调用者:通过命令对象执行请求。
- 接受者:执行请求相关的操作action。
- 命令模式结构。
- 客户端通过配置文件和反射创建具体命令对象,注入调用者。
实例
- 自定义功能键,用于退出系统或者显示文档帮助。用户可以通过配置文件修改功能键的用途,需要使得功能键类和功能类解耦。
扩展
命令队列
- 一个请求发送者发送请求时,有不止一个接受者产生响应,接受者逐个执行业务代码。类似批处理。
- 最常使用的实现方法是增加一个命令队列类CommandQueue,存储多个命令,执行的时候顺序执行。
记录请求日志
- 将请求的历史记录保存下来,通常使用日志文件。
- 请求日志可以:
- 系统故障时,提供一种恢复机制,恢复到某一特定状态。
- 存储一系列命令,如命令队列,实现批处理。
- 记录所有的请求,防止断电或者重启导致请求丢失。
撤销操作
- 可以在命令类中提供撤销恢复操作。
- 加法计算器在AddCommand中记录上一步操作数值,可以实现撤销一步操作,如果需要撤销多步等,需要记录历史操作类型和数值。
宏命令
- 组合命令,联用组合模式和命令模式,宏命令相当于组合模式中的容器构件,一般具体命令类相当于叶子构件。宏命令递归调用每个成员命令。
优缺点和适用环境
- 优点:
- 解耦请求者和接受者。降低系统耦合度,两者互相独立。
- 易于增加新的命令。只需继承,无需修改源码,符合开闭原则。
- 容易设计命令队列、宏命令。
- 实现撤销、恢复。
- 缺点:
- 过多具体命令类。针对每一个接受者的操作都需要一个命令类。
- 适用环境:
- 需要请求者和调用解耦。
- 需要在不同时间指定请求、排队、执行。命令对象和调用者生命周期可以不同。
- 需要支持撤销、恢复、宏命令。
jdk中的应用
- 线程池中,ThreadPoolExecutor是调用者,Runnable是抽象调用类,Thread等是具体调用类,这些具体调用类通过实现Runnable接口的run方法关联接受者。