将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
调用者,持有命令对象
public class MyInvoker { private Command command; public Command getCommand() { return command; } public void setCommand(Command command) { this.command = command; } public void invoke(){ command.action(); } }命令接口,一个命令对应一个事件
public interface Command { public void action(); }命令实现A,持有接收者对象
public class CommandImplA implements Command{ private MyReceiver receiver; public CommandImplA(MyReceiver receiver) { this.receiver = receiver; } @Override public void action() { this.receiver.executeA(); } }命令实现B
public class CommandImplB implements Command { private MyReceiver receiver; public CommandImplB(MyReceiver receiver) { this.receiver = receiver; } @Override public void action() { this.receiver.executeB(); } }命令实现C
public class CommandImplC implements Command { private MyReceiver receiver; public CommandImplC(MyReceiver receiver) { this.receiver = receiver; } @Override public void action() { this.receiver.executeC(); } }接受者,主要负责执行事件
public class MyReceiver { public void executeA(){ System.out.println("执行A事件"); } public void executeB(){ System.out.println("执行B事件"); } public void executeC(){ System.out.println("执行C事件"); } }测试类
public class CommandTest { public static void main(String[] args) { MyInvoker myInvoker = new MyInvoker(); MyReceiver myReceiver = new MyReceiver(); myInvoker.setCommand(new CommandImplA(myReceiver)); myInvoker.invoke(); myInvoker.setCommand(new CommandImplB(myReceiver)); myInvoker.invoke(); myInvoker.setCommand(new CommandImplC(myReceiver)); myInvoker.invoke(); } }可参考
Command模式的根本目的在于将“行为请求者”与“行为实现者”解耦,在面向对象语言中,常见的实现手段是“将行为抽象为对象”。实现Command接口的具体命令对象ConcreteCommand有时候根据需要可能会保存一些额外的状态信息。通过使用Compmosite模式,可以将多个命令封装为一个“复合命令”MacroCommand。Command模式与C#中的Delegate有些类似。但两者定义行为接口的规范有所区别:Command以面向对象中的“接口-实现”来定义行为接口规范,更严格,更符合抽象原则;Delegate以函数签名来定义行为接口规范,更灵活,但抽象能力比较弱。使用命令模式会导致某些系统有过多的具体命令类。某些系统可能需要几十个,几百个甚至几千个具体命令类,这会使命令模式在这样的系统里变得不实际。