意图:将一个请求封装为一个对象,从而可用不一样的请求对客户进行参数化;对请求排队或记录日志,以及支持可撤销的操做
动机:将”发出请求的对象”和”接收与执行这些请求的对象”分隔开来。
效果:
1)、command模式将调用操做的对象和实现该操做的对象解耦
2)、能够将多个命令装配成一个复合命令,复合命令是Composite模式的一个实例
3)、增长新的command很容易,无需改变已有的类
适用性:
1)、抽象出待执行的动做以参数化某对象
2)、在不一样的时刻指定、排列和执行请求。如请求队列
3)、支持取消操做
4)、支持修改日志
5)、用构建在原语操做上的高层操做构造一个系统。支持事物
参与者:
1)、Command
声明执行操做的接口
2)、ConcreteCommand
将一个接收者对象绑定于一个动做
调用接收者相应的操做,以实现execute
3)、Client
建立一个具体命令对象并设定它的接收者
4)、Invoker
要求该命令执行这个请求
5)、Receiver
知道如何实施与执行一个请求相关的操做。任何类均可能做为一个接收者
结构图:ide
协做:
1)、client建立一个ConcreteCommand对象并指定它的Receiver对象
2)、某Invoker对象存储该ConcreteCommand对象
3)、该Invoker经过调用Command对象的execute操做来提交一个请求。若该命令是可撤销的,ConcreteCommand在执行execute操做前存储当前状态以用于取消该命令
4)、ConcreteCommand对象调用它的Receiver的操做以执行该请求
命令对象将动做和接受者包进对象中,这个对象只暴露出一个execute()方法,当此方法被调用的时候,接收者就会进行这些动做。从外面来看,其余对象不知道究竟哪一个接收者进行了哪些动做,只知道若是调用execute()方法,请求的目的就能达到。 测试
实例:this
1 package com.test.patten.command; 2 3 /** 4 * 命令接口 5 */ 6 public interface Command { 7 /** 8 * 执行命令 9 */ 10 public void execute(); 11 /** 12 * 撤销命令 13 */ 14 public void undo(); 15 }
1 package com.test.patten.command; 2 3 /** 4 * 命令 5 */ 6 public class CreateCommand implements Command{ 7 private Receiver receiver; 8 private String state; 9 10 public CreateCommand(Receiver receiver){ 11 this.receiver = receiver; 12 } 13 14 @Override 15 public void execute() { 16 receiver.action(); 17 } 18 19 @Override 20 public void undo() { 21 receiver.unAction(); 22 } 23 24 }
1 package com.test.patten.command; 2 3 /** 4 * 命令接收者,命令真正执行人 5 */ 6 public class Receiver { 7 public void action(){ 8 System.out.println("执行命令..."); 9 } 10 11 public void unAction(){ 12 System.out.println("撤销命令..."); 13 } 14 }
1 package com.test.patten.command; 2 3 public class Invoker { 4 /** 5 * 调用者持有命令对象 6 */ 7 private Command command; 8 9 /** 10 * 设置命令对象 11 * @param command 12 */ 13 public void setCommand(Command command) { 14 this.command = command; 15 } 16 public Command getCommand() { 17 return command; 18 } 19 20 /** 21 * 执行命令 22 */ 23 public void runCommand(){ 24 command.execute(); 25 } 26 /** 27 * 撤销命令 28 */ 29 public void unDoCommand(){ 30 command.undo(); 31 } 32 }
1 package com.test.patten.command; 2 3 public class Client { 4 public static void main(String[] args){ 5 //建立接受者 6 Receiver receiver = new Receiver(); 7 //建立命令对象,并设置它的接受者 8 Command command = new CreateCommand(receiver); 9 10 //建立调用者,将命令对象设置进去 11 Invoker invoker = new Invoker(); 12 invoker.setCommand(command); 13 14 //这里能够测试一下 15 invoker.runCommand(); 16 invoker.unDoCommand(); 17 } 18 }
常见应用:
一、工做队列,线程池,日程安排
二、日志请求(系统恢复)
要点:
一、命令模式将发出请求的对象和执行请求的对象解耦
二、在被解耦的二者之间是经过命令对象进行沟通的。命令对象封装了接收者和一个或一组动做
三、调用者经过调用命令对象的execute()发出请求,这会使得接收者的动做被调用
四、调用者能够接受命令看成参数,甚至在运行时动态的进行
五、命令能够支持撤销,作法是实现一个undo()方法来回到execute()被执行前的状态
六、宏命令是命令的一种简单的延伸,容许调用多个命令。宏方法也能够支持撤销
七、实际操做时,很常见使用"聪明"命令对象,也就是直接实现了请求,而不是将工做委托给接受者(弊端?)
八、命令也能够用来实现日志和事物系统spa