一、概述
命令模式中,在发送者与接收者之间引入新的命令对象,将发送者的请求封装在命令对象中,再通过命令对象来调用接收者的方法。
命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。
命令模式的定义为:将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,又称为动作(Action)模式或事务(Transaction)模式。
命令模式的核心在于引入了命令类,通过命令类来降低发送者和接收者的耦合度,其结构图为:

二、示例代码
命令模式主要包含抽象命令类Command、具体命令类ConcreteCommand、调用者Invoker以及接收者Receiver。
抽象命令类Command典型代码如下:
1 | public abstract class Command { |
调用者类Invoker将针对抽象命令类进行编程,典型代码如下:
1 | public class Invoker { |
具体命令类ConcreteCommand继承抽象命令类,典型代码如下:
1 | public class ConcreteCommand extends Command { |
请求接收者类Receiver实现对请求的业务处理,典型代码如下:
1 | public class Receiver { |
命令队列
有时候需要将多个请求排队,当一个请求发送者发送一个请求时,不止一个接收者产生响应,此时可通过命令队列来实现。
命令队列可以通过增加一个CommandQueue类来实现,典型代码为:
1 | public class CommandQueue{ |
在增加了命令队列类CommandQueue后,请求发送者类Invoker将针对CommandQueue编程,典型代码为:
1 | public class Invoker { |
命令队列可以用于设计批处理应用程序,如果请求接收者的接收次序没有严格的先后次序,则还可以使用多线程技术来并发调用命令对象的execute()方法,从而提高程序的执行效率。
三、demo
给电视发出打开、调频道、关闭的命令,电视执行相应操作。
抽象命令类Command代码设计如下:
1 | public interface AbstractCommand { |
调用者类Invoker代码设计如下:
1 | public class Controller { |
具体命令类ConcreteCommand代码设计如下:
1 | public class TVChangeCommand implements AbstractCommand{ |
1 | public class TVCloseCommand implements AbstractCommand{ |
1 | public class TVOpenCommand implements AbstractCommand{ |
请求接收者类Receiver代码设计如下:
1 | public class Television { |
客户端调用代码如下:
1 | public static void main(String args[]) { |
代码运行结果如下:

四、总结
1. 优点
- 降低系统的耦合度。由于请求者与接收者之间不存在直接引用,因此请求者与接收者之间实现完全解耦,相同的请求者可以对应不同的接收者,同样,相同的接收者也可以供不同的请求者使用,两者之间具有良好的独立性。
- 新的命令可以很容易地加入到系统中。由于增加新的具体命令类不会影响到其他类,因此增加新的具体命令类很容易,无须修改原有系统源代码,甚至客户类代码,满足“开闭原则”的要求。
- 可以比较容易地设计一个命令队列或宏命令(组合命令)。
- 为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案。
2. 缺点
使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个对请求接收者的调用操作都需要设计一个具体命令类,因此在某些系统中可能需要提供大量的具体命令类,这将影响命令模式的使用。
3. 适用场景
- 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。请求调用者无须知道接收者的存在,也无须知道接收者是谁,接收者也无须关心何时被调用。
- 系统需要在不同的时间指定请求、将请求排队和执行请求。一个命令对象和请求的初始调用者可以有不同的生命期,换言之,最初的请求发出者可能已经不在了,而命令对象本身仍然是活动的,可以通过该命令对象去调用请求接收者,而无须关心请求调用者的存在性,可以通过请求日志文件等机制来具体实现。
- 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
- 系统需要将一组操作组合在一起形成宏命令。