命令模式关注动做自己,经过将动做封装成对象实现调用者和底层实现相分离。调用者只须要简单的下达命令,而后等待命令完成便可,对底层发生了什么彻底不知情。关于命令模式一个很直观的例子就是点餐:当咱们点餐时,咱们只用关心将选好的菜品下单,而后等待送餐便可,咱们不关心饭菜是怎么作的,不关心厨师是男是女。ide
下面经过一个万能遥控器的例子进一步认识命令模式。测试
步入物联网时代,不少家电均可以实现远程控制,咱们想看电视,听音乐,打扫房间,只须要按一下遥控器上对应的按键,相应的家电就会自动工做。那么这样的一款遥控器要怎样实现呢?如今的场景是,遥控器上的多个按钮对应多个家电,每一个家电都有“开”、“关”两个命令。固然,最重要的地方在于,遥控器还必需要可以方便扩展,之后购置新的家电时,只要加一些按钮就能够了。this
首先定义命令接口,为简单起见,命令接口里面只有execute方法,由于命令就是要被执行的:spa
1 public interface Command { 2 void execute(); 3 }
遥控器上的每个按钮都是一个命令,对应不一样的电器,因此命令应该有不少种具体类型,假设目前有灯泡、电视、音箱三种家电,电器的定义以下:3d
1 // 灯泡 2 public class Light { 3 public void on(){ 4 System.out.println("打开电灯。。。"); 5 } 6 7 public void off(){ 8 System.out.println("关闭电灯。。。"); 9 } 10 } 11 12 // 电视 13 public class TV { 14 public void on(){ 15 System.out.println("打开电视。。。"); 16 } 17 18 public void off(){ 19 System.out.println("关闭电视。。。"); 20 } 21 } 22 23 // 音箱 24 public class LoudspeakerBox { 25 public void on(){ 26 System.out.println("打开音箱。。。"); 27 } 28 29 public void off(){ 30 System.out.println("关闭音箱。。。"); 31 } 32 }
每种电器都有“开”、“关”两个具体命令,定义以下:code
1 // 开灯命令 2 public class LightOnCommand implements Command{ 3 Light light; 4 5 public LightOnCommand(Light light){ 6 this.light = light; 7 } 8 9 @Override 10 public void execute() { 11 light.on(); 12 } 13 } 14 15 // 关灯命令 16 public class LightOffCommand implements Command{ 17 Light light; 18 19 public LightOffCommand(Light light){ 20 this.light = light; 21 } 22 23 @Override 24 public void execute() { 25 light.off(); 26 } 27 } 28 29 // 电视和音箱的开关命令与此类型,略去 30 ...
如今能够看看遥控器的样子了:对象
1 // 遥控器 2 public class RemoteController { 3 Command[] onCommands; 4 Command[] offCommands; 5 6 public RemoteController(int commandSize){ 7 this.onCommands = new Command[commandSize]; 8 this.offCommands = new Command[commandSize]; 9 } 10 11 public void setCommand(int i, Command onCommand, Command offCommand){ 12 onCommands[i] = onCommand; 13 offCommands[i] = offCommand; 14 } 15 16 // 按下开按钮 17 public void onButtonPressed(int i){ 18 onCommands[i].execute(); 19 } 20 21 // 按下关按钮 22 public void offButtonPressed(int i){ 23 offCommands[i].execute(); 24 } 25 }
遥控器针对每一种家电设置了两个开关,按下对应的家电的对应开关,会触发相应的动做。这里只对接了3类家电,实际上彻底能够对接任意的家电。如今就须要写个测试类看看遥控器是否正常工做:blog
1 public class RemoteControllerTest { 2 public static void main(String[] args){ 3 Light light = new Light(); 4 TV tv = new TV(); 5 LoudspeakerBox loudspeakerBox = new LoudspeakerBox(); 6 Command lightOn = new LightOnCommand(light); 7 Command lightOff = new LightOffCommand(light); 8 Command TVOn = new TVOnCommand(tv); 9 Command TVOff = new TVOffCommand(tv); 10 Command LoudspeakerBoxOn = new LoudspeakerBoxOnCommand(loudspeakerBox); 11 Command LoudspeakerBoxOff = new LoudspeakerBoxOffCommand(loudspeakerBox); 12 13 RemoteController remoteController = new RemoteController(3); 14 remoteController.setCommand(0, lightOn, lightOff); 15 remoteController.setCommand(1, TVOn, TVOff); 16 remoteController.setCommand(2, LoudspeakerBoxOn, LoudspeakerBoxOff); 17 18 remoteController.onButtonPressed(0); 19 remoteController.offButtonPressed(0); 20 remoteController.onButtonPressed(1); 21 remoteController.offButtonPressed(1); 22 remoteController.onButtonPressed(2); 23 remoteController.offButtonPressed(2); 24 } 25 }
输出以下:接口
打开电灯。。。
关闭电灯。。。
打开电视。。。
关闭电视。。。
打开音箱。。。
关闭音箱。。。
遥控器看起来一块儿顺利。对以上的代码进行整理,能够得出命令模式的类图以下。rem
遥控器对应Client,各类家电的开关命令对应ConcreteCommand,Receiver就是家电。
以上就是命令模式的简单应用,它容许咱们将动做封装成命令对象,而后就能够为所欲为地存储、传递和调用它们了。经过命令对象实现调用者和执行者解耦,二者之间经过命令对象间接地进行沟通。