实例场景:java
一、餐馆点菜吃饭:当咱们在餐馆进行点菜的时候,通常咱们会进行点菜,而后服务员下订单,而后厨师根据订单进行炒菜,最后摆在咱们面前的就是一盘美味佳肴了。程序员
二、领导下命令:领导要员工作事的时候,通常是把事情告诉秘书或行政人员,而后由她们把领导安排的事情下发到员工。设计模式
三、当咱们想要听音乐,只要咱们按下播放键盘,相应的音乐就自动播放了。架构
以上场景中咱们都使用了一种设计模式:命令模式框架
命令模式把一个请求或者操做封装到一个对象中。命令模式运行系统使用不一样的请求把客户端参数化,对请求排队或者记录请求日志,能够提供命令的撤销和恢复功能。ide
命令模式中是把一个命令封装为一个对象。
测试
命令模式的角色:ui
客户角色:建立一个具体命令对象,并肯定其接受者this
命令角色:声明一个给全部具体命令类的抽象接口,这是一个抽象角色,一般由一个接口或抽象类实现。spa
具体命令角色:定义接收者和行为之间的弱耦合,实现execute方法,负责调用接收者的相应操做。
请求者角色:负责调用命令对象执行请求。
接收者角色:负责具体实施和执行一个请求。
在上面的实例场景中,场景分析以下:
一、餐馆点菜,咱们至关与一个客户角色,咱们点菜就是发送命令,不一样的人或有不一样的命令请求,就应该把命令设计为抽象类,用户发出的请求就是具体的命令,服务员就是一个请求者,她把命令也就是客户的订单给接受者厨师,厨师只要照着菜单作菜,作好后给客户便可,客户不用去管菜是怎样作出来的,只要发送一个命令,而后获得本身的结果就能够了。
二、领导下命令:我是老总,我只管发个命令,至于这个命令发给谁,谁执行,关我P事,我发钱请人不是为了给本身找麻烦。你是负责事情的员工,你的天职是作好上级交给你的任务,踏踏实实,不要知道太多,不要八卦,不要问太多了。Client对象是发布命令的。Invoker对象是传递命令的,就是跑腿的。Receiver是受气包,底层最累的程序员,负责干活吧
三、一个Mp3。你按了一个播放键盘,就播放了。这就能够算是命令模式的一种。 你是Client ,按键是Invoker,mp3是Receiver,播放就是一个命令Command对象。
命令模式的好处:
◆很容易构造一个命令队列
◆记录相关的命令日志
◆增长命令的状态,实现命令的撤销和重作
◆容许接受请求的一方决定是否可作
◆新的命令垂手可得能够加入其中
缺点:可能会有过多的具体命令类存在
场景代码实现:
package cn.com.command; //声明一个命令角色 public interface Command { public void execute(); }
package cn.com.command; //定义一个接收者,至关与一个厨师 //负责具体实施和执行一个请求 public class Recevier { public void doAction(){ System.out.println("客户发订单了,我要炒菜了"); } }
package cn.com.command; //具体的命令角色,负责调用接收者相应的操做 public class ConcreteCommand implements Command{ private Recevier recevier; public ConcreteCommand(Recevier recevier){ this.recevier=recevier; } @Override public void execute() { recevier.doAction(); } }
package cn.com.command; //定义一个请求者角色, //负责调用命令对象,执行请求 public class Invoker { private Command command; public Invoker(Command command){ this.command=command; } public void doInvokerAction(){ command.execute(); } }
package cn.com.command; //建立客户角色,客户进行点菜 public class Client { public static void main(String[] args) { //生成一个具体的厨师角色 Recevier recevier=new Recevier(); //生成一个菜单命令对象 Command command=new ConcreteCommand(recevier); //服务员把菜单给厨师,厨师具体实施,进行炒菜 Invoker invoker=new Invoker(command); invoker.doInvokerAction(); //在整个应用场景中,其实是请求者调用具体命令对象,具体命令对象调用接收者 } }
客户发订单了,我要炒菜了
//在整个应用场景中,其实是请求者调用具体命令对象,具体命令对象调用接收者
在JUnit框架中,运用了咱们的命令模式:
用户编写测试用例TestCase,把这些测试用例组成请求(多是一个或者多个),发送到JUnit,而后由JUnit执行,最后报告详细测试结果包括执行的时间,错误方法,错误位置等。这样测试用例的开发人员就不须要知道请求TestCase的具体操做信息,仅把它看成一种命令来执行,而后把执行测试结果发给测试人员。这样就使JUnit框架和TestCase的开发人员独立开来,使得请求的一方没必要知道接收请求一方的详细信息,更没必要知道是怎样被接收,以及怎样被执行的,实现系统的松藕合。
使用命令模式后给JUnit系统的架构带来的效果:
a、将实现请求的一方(TestCase开发)和调用一方JUnit进行解耦
b、使新的TestCase很容易加入,无需改变已有的类,只需继承TestCase类便可,这样方便了测试人员
c、能够将多个TestCase进行组合成一个复合命令,TestSuit就是它的复合命令,使用了组合模式
d、容易把请求的TestCase组成请求队列,这样使接收请求的一方JUnit框架,容易决定是否执行请求,一旦发现测试用例失败或者错误能够当即中止进行报告