定义
命令模式(Command Pattern)又称为行动(Action)模式或者交易(Transaction)模式。
英文原话:Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations.
翻译:将一个请求封装成一个对象,从而让你能使用不同的请求把客户端参数化,对于请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
角色:
命令(Command)角色:该角色声明一个给所有具体命令类的抽象接口,定义需要执行的命令。
具体命令(Concrete Command)角色:该角色定义一个接收者和行为之间的弱耦合,实现命令方法,并调用接受者的相应操作。
调用者(Invoker)角色:该角色负责调用命令对象的执行请求。
接收者(Receive)角色:该角色负责具体实施和执行一个请求。
/** * 命令接口 */ public interface Command { //执行命令方法 public void execute(); } /** * 具体命令角色 */ public class ConcreteCommand implements Command { private Receiver receiver; public ConcreteCommand(Receiver receiver) { this.receiver = receiver; } @Override public void execute() { this.receiver.action(); } } /** * 接收者 */ public class Receiver { //行动方法 public void action(){ System.out.println("执行动作"); } } /** * 调用者 */ public class Invoker { private Command command; //接收命令 public void setCommand(Command command){ this.command = command; } //执行命令 public void action(){ this.command.execute(); } } /** * 测试类 */ public class Client { public static void main(String[] args) { //调用者 Invoker invoker = new Invoker(); //接收者 Receiver receiver = new Receiver(); //定义一个发送给接收者的命令 Command command = new ConcreteCommand(receiver); //执行 invoker.setCommand(command); invoker.action(); } }
优点
- 类间解耦。调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需调用Command中的execute()方法即可,不需要了解是哪个接收者来执行。
- 可扩展性。Command的子类非常容易扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。
- 命令模式结合其他模式会更优秀。命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,可以减少Command子类的膨胀。
缺点
使用命令模式可能会导致系统中出现过多的具体命令类,因此在项目中使用命令模式时需要慎重考虑。
应用场景
- 使用命令模式作为“回调”在面向对象系统中的代替。“回调”就是将一个函数登记,方便在以后调用此函数。
- 需要在不同的时间指定请求、将请求排队。
- 系统需要支持命令的撤销(undo)。命令对象可以把状态存储起来,等到客户端需要撤销时,可以调用undo()方法,将命令所产生的效果撤销。
- 需要将系统中所有的数据更新操作保存到日志里,以便在系统崩溃时,可以根据日志读回所有的数据更新命令,重新调用execute()方法,一条一条执行这些命令,从而恢复系统在崩溃前所做的数据更新。
- 一个系统需要支持交易(transaction)。一个交易结构封装了一组数据更新命令。使用命令模式来实现交易结构可以使系统增加新的交易类型。
/** * 命令接收者 */ public class Receiver { public void turnON(){ System.out.println("开灯~~~"); } public void turnOFF(){ System.out.println("熄灯~~~"); } } /** * 命令接口 */ public interface Command { public void execute(); } /** * 开灯命令 */ public class LightOnCommand implements Command{ private Receiver receiver; public LightOnCommand(Receiver receiver) { this.receiver = receiver; } @Override public void execute() { this.receiver.turnON(); } } /** * 关灯命令 */ public class LightOffCommand implements Command{ private Receiver receiver; public LightOffCommand(Receiver receiver) { this.receiver = receiver; } @Override public void execute() { receiver.turnOFF(); } } /** * 调用者 */ public class Invoker { public void invoker(Command command){ command.execute(); //执行命令 } } /** * 测试类 */ public class Main { public static void main(String[] args) { Receiver receiver = new Receiver(); //接收者 Command command1 = new LightOnCommand(receiver); //开灯命令 Command command2 = new LightOffCommand(receiver); //开灯命令 Invoker invoker = new Invoker(); invoker.invoker(command1); invoker.invoker(command2); } }