命令模式-接收者与执行者解耦和
老板:阿飞,咱们公司又接了个新项目,一个客户,,卧室和客厅很大,电灯电视开关也不好找,所以希望制造一个遥控器来控制一些家具的开启与关闭,目前需要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 }
然后建立了一个对象,代表了空对象,什么操作也不执行
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 }
测试结果
---------------------------------------------未赋值之前------------------------------------------------ [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 ****************************************************************************************************** 卧室_灯打开 卧室_灯关闭 卧室_电视打开 卧室_电视关闭 客厅_灯打开 客厅_灯关闭 客厅_电视打开 客厅_电视关闭
阿三:飞哥,我这里使用的设计模式-命令模式,
将动作执行(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(); } }
测试类新增撤销测试
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"); } }
修改之后的测试结果
---------------------------------------------未赋值之前------------------------------------------------ [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 ****************************************************************************************************** 卧室_灯打开 卧室_灯关闭 ---撤销--- 卧室_灯打开 ---撤销--- 卧室_灯打开 卧室_电视打开 卧室_电视关闭 ---撤销--- 卧室_电视打开 客厅_灯打开 客厅_灯关闭 ---撤销--- 客厅_灯打开 客厅_电视打开 客厅_电视关闭 ---撤销--- 客厅_电视打开
项目组长阿飞:不错,不错,以后给你涨工资。
下一篇: MSI P9N主板跑D5的故障一例