将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。
类型
行为型
参与者
- Command(抽象命令类):抽象命令类一般是一个抽象类或接口,在其中声明了用于执行请求的execute()等方法,通过这些方法可以调用请求接收者的相关操作。
- ConcreteCommand(具体命令类):具体命令类是抽象命令类的子类,实现了在抽象命令类中声明的方法,它对应具体的接收者对象,将接收者对象的动作绑定其中。在实现execute()方法时,将调用接收者对象的相关操作(Action)。
- Invoker(调用者):调用者即请求发送者,它通过命令对象来执行请求。一个<u>调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联关系。</u>在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的execute()方法,从而实现间接调用请求接收者的相关操作。
- Receiver(接收者):接收者执行与请求相关的操作,它具体实现对请求的业务处理。
用法
标准使用
代码助记:
客户端根据实际情况为invoke注入相应的command,在每个command实现类中,自己维护(关联关系)相对应的receiver。这样,对于客户端来说,其只知道如何发出命令,后续操作实现对其是透明的。
也即,将一个请求封装为一个对象,用不同的请求对客户进行参数化。
命令队列的实现
引入一个cmdQueue存储多个Command。当invoke发送一个请求时,将不止一个请求接收者产生响应,这些请求接收者将逐个执行业务方法,完成对请求的处理。
撤销/恢复撤销操作的实现
在抽象command类中,增加一个undo()/redo()方法来实现逆向操作。
多次撤销:通过引入一个命令集合或其他方式来存储每一次操作时命令的状态,从而实现多次撤销操作。
另一种撤销思路:通过保存对象的历史状态来实现,备忘录模式。
请求日志
请求日志就是将请求的历史记录保存下来,通常以日志文件(Log File)的形式永久存储在计算机中。将命令对象通过序列化写到日志文件中,此时命令类必须实现Java.io.Serializable接口。
请求日志文件可以实现很多功能,常用功能如下:
- “天有不测风云”,一旦系统发生故障,日志文件可以为系统提供一种恢复机制,在请求日志文件中可以记录用户对系统的每一步操作,从而让系统能够顺利恢复到某一个特定的状态;
- 请求日志也可以用于实现批处理,在一个请求日志文件中可以存储一系列命令对象,例如一个命令队列;
- 可以将命令队列中的所有命令对象都存储在一个日志文件中,每执行一个命令则从日志文件中删除一个对应的命令对象,防止因为断电或者系统重启等原因造成请求丢失,而且可以避免重新发送全部请求时造成某些命令的重复执行,只需读取请求日志文件,再继续执行文件中剩余的命令即可。
总结
- 命令模式可以将 请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。
- 命令模式的关键在于引入了抽象命令类,请求发送者针对抽象命令类编程,只有实现了抽象命令类的具体命令才与请求接收者相关联。