命令模式-接收者与执行者解耦和
将动作执行与接收者包装到对象里面,对外暴露的只有一个接口中的execute方法,其他对象不需要知道那个接收者执行了什么动作,只需要知道调用execute,就能完成一个请求的操作
老板:阿飞,咱们公司又接了个新项目,一个客户,,卧室和客厅很大,电灯电视开关也不好找,所以希望制造一个遥控器来控制一些家具的开启与关闭,目前需要5个按键,卧室的灯,卧室的电视,客厅的灯,客厅的电视,在留一个预备按键。我等会把需求文档给你。
项目组长阿飞:好的,老板
项目组长阿飞:小三,来了个需求,你看下,你先设计一下架构
阿三:好的,飞哥
三天过后:飞哥,好了,你看下
先设计了一个接口,里面包含了,每一个按钮的统一行为
1 package com.commandPattern.command; 2 3 /** 4 * @program: testPattern 5 * @description: 命令接口 6 * @author: Mr.Yang 7 * @create: 2018-12-08 13:54 8 **/ 9 public interface Command { 10 11 //执行方法 12 public void exceute(); 13 14 }
View Code
然后建立了一个对象,代表了空对象,什么操作也不执行
package com.commandPattern.command.nullCommand; import com.commandPattern.command.Command; /** * @program: testPattern * @description: 建立一个空对象,在许多设计模式种,都会看到空对象的使用,甚至有些时候,空对象本身也被视为一种设计模式 * @author: Mr.Yang * @create: 2018-12-08 17:40 **/ public class NullCommand implements Command { public void exceute() { System.out.println("什么都不做处理"); } }
灯的具体类
package com.commandPattern.entity; /** * @program: testPattern * @description: 灯的具体类 * @author: Mr.Yang * @create: 2018-12-08 17:31 **/ public class Lamp { private String name; /** * name为灯的具体装饰,即为哪里的灯 * @param name */ public Lamp(String name){ this.name=name; } public void on (){ System.out.println(name+"_灯打开"); } public void off (){ System.out.println(name+"_灯关闭"); } }
电视的具体类
package com.commandPattern.entity; /** * @program: testPattern * @description: 电视的具体类 * @author: Mr.Yang * @create: 2018-12-08 17:35 **/ public class Tv { private String name; public Tv(String name){ this.name=name; } public void on (){ System.out.println(name+"_电视打开"); } public void off(){ System.out.println(name+"_电视关闭"); } }
关闭灯的具体命令
package com.commandPattern.command.off; import com.commandPattern.command.Command; import com.commandPattern.entity.Lamp; /** * @program: testPattern * @description: 灯关闭 * @author: Mr.Yang * @create: 2018-12-08 17:33 **/ public class LampOffCommand implements Command { Lamp lamp; public LampOffCommand(Lamp lamp){ this.lamp=lamp; } //灯关闭 public void exceute() { lamp.off(); } }
打开灯的具体命令
package com.commandPattern.command.on; import com.commandPattern.command.Command; import com.commandPattern.entity.Lamp; /** * @program: testPattern * @description: 灯打开的命令 * @author: Mr.Yang * @create: 2018-12-08 17:29 **/ public class LampOnCommand implements Command { Lamp lamp; public LampOnCommand(Lamp lamp){ this.lamp=lamp; } //灯打开的命令 public void exceute() { lamp.on(); } }
电视关闭的具体命令
package com.commandPattern.command.off; import com.commandPattern.command.Command; import com.commandPattern.entity.Tv; /** * @program: testPattern * @description: 电视关闭 * @author: Mr.Yang * @create: 2018-12-08 17:36 **/ public class TvOffCommand implements Command { Tv tv; public TvOffCommand(Tv tv){ this.tv=tv; } public void exceute() { tv.off(); } }
电视打开的具体命令
package com.commandPattern.command.on; import com.commandPattern.command.Command; import com.commandPattern.entity.Tv; /** * @program: testPattern * @description: 电视打开 * @author: Mr.Yang * @create: 2018-12-08 17:37 **/ public class TvOnCommand implements Command { Tv tv; public TvOnCommand(Tv tv){ this.tv=tv; } public void exceute() { tv.on(); } }
建立一个遥控器
package com.commandPattern.control; import com.commandPattern.command.Command; import com.commandPattern.command.nullCommand.NullCommand; import java.util.Arrays; /** * @program: testPattern * @description: 遥控器 * @author: Mr.Yang * @create: 2018-12-08 17:39 **/ public class RemoteControl { Command[] onCommand; Command[] offCommand; //初始化每个操作为空操作 public RemoteControl(){ onCommand=new Command[5]; offCommand=new Command[5]; NullCommand nullCommand = new NullCommand(); for (int i = 0; i < 5; i++) { onCommand[i]=nullCommand; offCommand[i]=nullCommand; } } public void setCommond(int index,Command onCommand,Command offCommand){ this.offCommand[index]=offCommand; this.onCommand[index]=onCommand; } public void clickOn(int index){ onCommand[index].exceute(); } public void clickOff(int index){ offCommand[index].exceute(); } /** * 输出每个按钮的具体代表类 * @return */ @Override public String toString() { StringBuffer sb = new StringBuffer(); for (int i = 0; i < onCommand.length; i++) { sb.append("[index : "+i+"] "); sb.append(onCommand[i].getClass().getName()); sb.append(" "); sb.append(offCommand[i].getClass().getName()); sb.append("\r\n"); } return sb.toString(); } }
测试类
1 package com.commandPattern.testPattern; 2 3 import com.commandPattern.command.off.LampOffCommand; 4 import com.commandPattern.command.off.TvOffCommand; 5 import com.commandPattern.command.on.LampOnCommand; 6 import com.commandPattern.command.on.TvOnCommand; 7 import com.commandPattern.control.RemoteControl; 8 import com.commandPattern.entity.Lamp; 9 import com.commandPattern.entity.Tv; 10 11 /** 12 * @program: test 13 * @description: 14 * @author: Mr.Yang 15 * @create: 2018-12-08 17:48 16 **/ 17 public class TestPattern { 18 public static void main(String[] args) { 19 RemoteControl remoteControl = new RemoteControl(); 20 21 /** 22 * 创建装置到合适位置 23 */ 24 Tv bedRoomTV = new Tv("卧室"); 25 Tv drawiTV = new Tv("客厅"); 26 27 Lamp bedRoomLamp = new Lamp("卧室"); 28 Lamp drawiLamp = new Lamp("客厅"); 29 30 /** 31 * 创建所有命令操作对象 32 */ 33 //卧室灯关闭对象 34 LampOffCommand bedLampOffCommand = new LampOffCommand(bedRoomLamp); 35 //卧室灯打开对象 36 LampOnCommand bedLampOnCommand = new LampOnCommand(bedRoomLamp); 37 //卧室TV关闭对象 38 TvOffCommand bedTvOffCommand = new TvOffCommand(bedRoomTV); 39 //卧室TV打开对象 40 TvOnCommand bedTVcommand = new TvOnCommand(bedRoomTV); 41 //客厅灯打开对象 42 LampOnCommand drawLampOnCommand = new LampOnCommand(drawiLamp); 43 //客厅灯关闭对象 44 LampOffCommand drawLampOffCommand = new LampOffCommand(drawiLamp); 45 //客厅TV关闭对象 46 TvOffCommand drawTVOffCommand = new TvOffCommand(drawiTV); 47 //客厅TV打开对象 48 TvOnCommand drawTVOnCommand = new TvOnCommand(drawiTV); 49 50 System.out.println("---------------------------------------------未赋值之前------------------------------------------------"); 51 System.out.println(remoteControl); 52 System.out.println("******************************************************************************************************"); 53 54 /** 55 * //将操作对象与卡槽一一对应 56 */ 57 //赋值卧室灯打开与关闭 58 remoteControl.setCommond(0,bedLampOnCommand,bedLampOffCommand); 59 //赋值卧室TV打开与关闭 60 remoteControl.setCommond(1,bedTVcommand,bedTvOffCommand); 61 //赋值客厅灯打开与关闭 62 remoteControl.setCommond(2,drawLampOnCommand,drawLampOffCommand); 63 //赋值客厅TV打开与关闭 64 remoteControl.setCommond(3,drawTVOnCommand,drawTVOffCommand); 65 66 System.out.println("---------------------------------------------赋值之后------------------------------------------------"); 67 System.out.println(remoteControl); 68 System.out.println("******************************************************************************************************"); 69 70 71 /** 72 * 测试每一个按钮 73 */ 74 remoteControl.clickOn(0); 75 remoteControl.clickOff(0); 76 77 remoteControl.clickOn(1); 78 remoteControl.clickOff(1); 79 80 remoteControl.clickOn(2); 81 remoteControl.clickOff(2); 82 83 remoteControl.clickOn(3); 84 remoteControl.clickOff(3); 85 86 87 } 88 }
View Code
测试结果
---------------------------------------------未赋值之前------------------------------------------------ [index : 0] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand [index : 1] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand [index : 2] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand [index : 3] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand [index : 4] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand ****************************************************************************************************** ---------------------------------------------赋值之后------------------------------------------------ [index : 0] com.commandPattern.command.on.LampOnCommand com.commandPattern.command.off.LampOffCommand [index : 1] com.commandPattern.command.on.TvOnCommand com.commandPattern.command.off.TvOffCommand [index : 2] com.commandPattern.command.on.LampOnCommand com.commandPattern.command.off.LampOffCommand [index : 3] com.commandPattern.command.on.TvOnCommand com.commandPattern.command.off.TvOffCommand [index : 4] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand ****************************************************************************************************** 卧室_灯打开 卧室_灯关闭 卧室_电视打开 卧室_电视关闭 客厅_灯打开 客厅_灯关闭 客厅_电视打开 客厅_电视关闭
View Code
阿三:飞哥,我这里使用的设计模式-命令模式,
将动作执行(LampOnCommand,TvOnCommand……)与接收者(Lamp,Tv)包装到对象里面,对外暴露的只有一个Command接口中的execute方法,其他对象不需要知道那个接收者执行了什么动作,只需要知道调用execute,就能完成一个请求的操作,这个对象,与其他对象没有关联,完全解耦和,如果需要做新增,不需要修改原有代码,拓展接收者类和动作执行类,就能实现功能。
项目组长阿飞:不错,不错,进步很大。
项目组长阿飞:第5个按钮可能需要做一个恢复上一步动作的效果,类似于CTRL+Z这个效果,你再改改把。
阿三:好的。
阿三:飞哥修改好了,你看下
命令接口新增撤销方法
package com.commandPattern.command; /** * @program: testPattern * @description: 命令接口 * @author: Mr.Yang * @create: 2018-12-08 13:54 **/ public interface Command { //执行方法 public void exceute(); //撤销方法 public void revoke(); }
建立一个空对象,实现了撤销方法
package com.commandPattern.command.nullCommand; import com.commandPattern.command.Command; /** * @program: testPattern * @description: 建立一个空对象,在许多设计模式种,都会看到空对象的使用,甚至有些时候,空对象本身也被视为一种设计模式 * @author: Mr.Yang * @create: 2018-12-08 17:40 **/ public class NullCommand implements Command { public void exceute() { System.out.println("什么都不做处理"); } public void revoke() { System.out.println("什么都不做处理"); } }
灯关闭实现了撤销方法
package com.commandPattern.command.off; import com.commandPattern.command.Command; import com.commandPattern.entity.Lamp; /** * @program: testPattern * @description: 灯关闭 * @author: Mr.Yang * @create: 2018-12-08 17:33 **/ public class LampOffCommand implements Command { Lamp lamp; public LampOffCommand(Lamp lamp){ this.lamp=lamp; } //灯关闭 public void exceute() { lamp.off(); } //执行到这个具体实现类,代表上一步是灯关闭,撤销操作即为灯打开 public void revoke() { lamp.on(); } }
灯打开实现了撤销方法
package com.commandPattern.command.on; import com.commandPattern.command.Command; import com.commandPattern.entity.Lamp; /** * @program: testPattern * @description: 灯打开的命令 * @author: Mr.Yang * @create: 2018-12-08 17:29 **/ public class LampOnCommand implements Command { Lamp lamp; public LampOnCommand(Lamp lamp){ this.lamp=lamp; } //灯打开的命令 public void exceute() { lamp.on(); } //执行到这个具体实现类,代表上一步是灯打开,撤销操作即为灯关闭 public void revoke() { lamp.off(); } }
电视关闭实现了撤销方法
package com.commandPattern.command.off; import com.commandPattern.command.Command; import com.commandPattern.entity.Tv; /** * @program: testPattern * @description: 电视关闭 * @author: Mr.Yang * @create: 2018-12-08 17:36 **/ public class TvOffCommand implements Command { Tv tv; public TvOffCommand(Tv tv){ this.tv=tv; } public void exceute() { tv.off(); } //执行到这个具体实现类,代表上一步是电视关闭,撤销操作即为电视打开 public void revoke() { tv.on(); } }
电视打开实现了撤销方法
package com.commandPattern.command.on; import com.commandPattern.command.Command; import com.commandPattern.entity.Tv; /** * @program: testPattern * @description: 电视打开 * @author: Mr.Yang * @create: 2018-12-08 17:37 **/ public class TvOnCommand implements Command { Tv tv; public TvOnCommand(Tv tv){ this.tv=tv; } public void exceute() { tv.on(); } //执行到这个具体实现类,代表上一步是电视打开,撤销操作即为电视关闭 public void revoke() { tv.off(); } }
遥控器类,新增变量记录上一步操作
package com.commandPattern.control; import com.commandPattern.command.Command; import com.commandPattern.command.nullCommand.NullCommand; import java.util.Arrays; /** * @program: testPattern * @description: 遥控器 * @author: Mr.Yang * @create: 2018-12-08 17:39 **/ public class RemoteControl { Command[] onCommand; Command[] offCommand; //这个变量来记录上一个命令 Command upStepCommand; //初始化每个操作为空操作 public RemoteControl(){ onCommand=new Command[5]; offCommand=new Command[5]; NullCommand nullCommand = new NullCommand(); for (int i = 0; i < 5; i++) { onCommand[i]=nullCommand; offCommand[i]=nullCommand; } upStepCommand=nullCommand; } public void setCommond(int index,Command onCommand,Command offCommand){ this.offCommand[index]=offCommand; this.onCommand[index]=onCommand; } //新增upStepCommand记录上一步命令 public void clickOn(int index){ onCommand[index].exceute(); upStepCommand=onCommand[index]; } //新增upStepCommand记录上一步命令 public void clickOff(int index){ offCommand[index].exceute(); upStepCommand=offCommand[index]; } public void toUpStepClick(){ System.out.println("---撤销---"); upStepCommand.revoke(); } /** * 输出每个按钮的具体代表类 * @return */ @Override public String toString() { StringBuffer sb = new StringBuffer(); for (int i = 0; i < onCommand.length; i++) { sb.append("[index : "+i+"] "); sb.append(onCommand[i].getClass().getName()); sb.append(" "); sb.append(offCommand[i].getClass().getName()); sb.append("\r\n"); } return sb.toString(); } }
View Code
测试类新增撤销测试
package com.commandPattern.testPattern; import com.commandPattern.command.off.LampOffCommand; import com.commandPattern.command.off.TvOffCommand; import com.commandPattern.command.on.LampOnCommand; import com.commandPattern.command.on.TvOnCommand; import com.commandPattern.control.RemoteControl; import com.commandPattern.entity.Lamp; import com.commandPattern.entity.Tv; /** * @program: test * @description: * @author: Mr.Yang * @create: 2018-12-08 17:48 **/ public class TestPattern { public static void main(String[] args) { RemoteControl remoteControl = new RemoteControl(); /** * 创建装置到合适位置 */ Tv bedRoomTV = new Tv("卧室"); Tv drawiTV = new Tv("客厅"); Lamp bedRoomLamp = new Lamp("卧室"); Lamp drawiLamp = new Lamp("客厅"); /** * 创建所有命令操作对象 */ //卧室灯关闭对象 LampOffCommand bedLampOffCommand = new LampOffCommand(bedRoomLamp); //卧室灯打开对象 LampOnCommand bedLampOnCommand = new LampOnCommand(bedRoomLamp); //卧室TV关闭对象 TvOffCommand bedTvOffCommand = new TvOffCommand(bedRoomTV); //卧室TV打开对象 TvOnCommand bedTVcommand = new TvOnCommand(bedRoomTV); //客厅灯打开对象 LampOnCommand drawLampOnCommand = new LampOnCommand(drawiLamp); //客厅灯关闭对象 LampOffCommand drawLampOffCommand = new LampOffCommand(drawiLamp); //客厅TV关闭对象 TvOffCommand drawTVOffCommand = new TvOffCommand(drawiTV); //客厅TV打开对象 TvOnCommand drawTVOnCommand = new TvOnCommand(drawiTV); System.out.println("---------------------------------------------未赋值之前------------------------------------------------"); System.out.println(remoteControl); System.out.println("******************************************************************************************************"); /** * //将操作对象与卡槽一一对应 */ //赋值卧室灯打开与关闭 remoteControl.setCommond(0,bedLampOnCommand,bedLampOffCommand); //赋值卧室TV打开与关闭 remoteControl.setCommond(1,bedTVcommand,bedTvOffCommand); //赋值客厅灯打开与关闭 remoteControl.setCommond(2,drawLampOnCommand,drawLampOffCommand); //赋值客厅TV打开与关闭 remoteControl.setCommond(3,drawTVOnCommand,drawTVOffCommand); System.out.println("---------------------------------------------赋值之后------------------------------------------------"); System.out.println(remoteControl); System.out.println("******************************************************************************************************"); /** * 测试每一个按钮 */ remoteControl.clickOn(0); remoteControl.clickOff(0); //撤销一次 remoteControl.toUpStepClick(); System.out.println("\r\n"); //撤销一次 remoteControl.toUpStepClick(); System.out.println("\r\n"); remoteControl.clickOn(1); remoteControl.clickOff(1); //撤销一次 remoteControl.toUpStepClick(); System.out.println("\r\n"); remoteControl.clickOn(2); remoteControl.clickOff(2); //撤销一次 remoteControl.toUpStepClick(); System.out.println("\r\n"); remoteControl.clickOn(3); remoteControl.clickOff(3); //撤销一次 remoteControl.toUpStepClick(); System.out.println("\r\n"); } }
View Code
修改之后的测试结果
---------------------------------------------未赋值之前------------------------------------------------ [index : 0] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand [index : 1] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand [index : 2] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand [index : 3] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand [index : 4] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand ****************************************************************************************************** ---------------------------------------------赋值之后------------------------------------------------ [index : 0] com.commandPattern.command.on.LampOnCommand com.commandPattern.command.off.LampOffCommand [index : 1] com.commandPattern.command.on.TvOnCommand com.commandPattern.command.off.TvOffCommand [index : 2] com.commandPattern.command.on.LampOnCommand com.commandPattern.command.off.LampOffCommand [index : 3] com.commandPattern.command.on.TvOnCommand com.commandPattern.command.off.TvOffCommand [index : 4] com.commandPattern.command.nullCommand.NullCommand com.commandPattern.command.nullCommand.NullCommand ****************************************************************************************************** 卧室_灯打开 卧室_灯关闭 ---撤销--- 卧室_灯打开 ---撤销--- 卧室_灯打开 卧室_电视打开 卧室_电视关闭 ---撤销--- 卧室_电视打开 客厅_灯打开 客厅_灯关闭 ---撤销--- 客厅_灯打开 客厅_电视打开 客厅_电视关闭 ---撤销--- 客厅_电视打开
View Code
项目组长阿飞:不错,不错,以后给你涨工资。