@BertLee
2017-08-19T02:17:57.000000Z
字数 3280
阅读 1038
命令模式把发出命令的责任和执行命令的责任分隔开,分别委托给不同的对象。
每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。
命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
使用命令模式会导致系统增加过度的具体命令类,使得其实现不切合实际。
命令模式涉及到5个角色,分别是:
- 命令角色:接口或者抽象类,抽象方法包含了命令的执行操作
- 具体命令角色:类,实现命令的执行方法,调用接受者的相应操作
- 请求者角色:类,负责调用命令的执行请求,相关的方法,叫行动方法
- 接受者角色:类,负责具体实施和执行1个请求,相关的方法,叫行动方法
电视机会有开机,关机,换台的基本命令操作,我们不需要知道其内部实现,在这里我们是客户端,而电视机可以被看做命令接受者,遥控器则可以被看做是命令请求者,我们只需要和请求者打交道即可。
命令模式的结构如下图:
套路:
1. 将接受者要执行的命令拆分,分别创建对应的命令类,并把接受者对象委托到命令类中
2. 创建请求者类,添加所有命令的委托对象,对于各自的命令,要创建各自的行动方法
/*** 命令接受者-电视机*/public class TV {private int currentChannel = 0;//行动方法public void trunOn(){System.out.println("电视机开启");}//行动方法public void turnOff(){System.out.println("电视机关闭");}//行动方法public void change(int channel){this.currentChannel = channel;System.out.println("切换到频道" + currentChannel);}}
/*** 命令接口*/public interface Command {public void execute();}
/*** 打开命令*/public class OnCommand implements Command{private TV tv;public OnCommand(TV tv){this.tv = tv;}public void execute() {tv.trunOn();}}
/*** 换台命令*/public class ChangeCommand implements Command{private TV tv;private int channel;public ChangeCommand(TV tv,int channel){this.tv = tv;this.channel = channel;}public void execute() {tv.change(channel);}}
/*** 关闭命令*/public class OffCommand implements Command {private TV tv;public OffCommand(TV tv){this.tv = tv;}public void execute() {tv.turnOff();}}
/*** 复合命令,由多个连续的基本命令操作组成*/public class ManyCommand implements Command{//可设计为命令队列private List<Command> commands = new ArrayList<Command>();public void add(Command command){commands.add(command);}public void remove(Command command){commands.remove(command);}public void execute() {for(Command command :commands){command.execute();}}}
/*** 命令请求者-遥控器*/public class Control {private Command offCommand;private Command onCommand;private Command changeCommand;private Command manyCommand;//行动方法public void turnOn(){onCommand.execute();}//行动方法public void trunOff(){offCommand.execute();}//行动方法public void change(){changeCommand.execute();}//行动方法public void exeManyCommand(){manyCommand.execute();}public void setOffCommand(Command offCommand) {this.offCommand = offCommand;}public void setOnCommand(Command onCommand) {this.onCommand = onCommand;}public void setChangeCommand(Command changeCommand) {this.changeCommand = changeCommand;}public void setManyCommand(Command manyCommand) {this.manyCommand = manyCommand;}}
/*** 测试命令模式*/public class CommandTest {@Testpublic void testCommand(){//命令接受者TV tv = new TV();//命令,绑定接受者OnCommand onCommand = new OnCommand(tv);ChangeCommand changeCommand = new ChangeCommand(tv, 3);OffCommand offCommand = new OffCommand(tv);//命令请求者,绑定命令Control control = new Control();control.setOnCommand(onCommand);control.setChangeCommand(changeCommand);control.setOffCommand(offCommand);//触发control.turnOn();control.trunOff();control.change();//复合命令ManyCommand manyCommand = new ManyCommand();manyCommand.add(onCommand);manyCommand.add(changeCommand);manyCommand.add(offCommand);//命令请求者绑定复合命令control.setManyCommand(manyCommand);//触发control.exeManyCommand();}}
吹牛:
1. 命令模式将对象的请求操作和执行操作分割开来,实现解耦
2. 命令模式使新的命令很容易地被加入到系统里。、
3. 能较容易地设计一个命令队列。
4. 可以容易地实现对请求的撤销和恢复。应用场景:
- 可使用命令模式作为回调。先将行动方法注册上,然后在需要时调用。
- 需要在不同的时间制定请求、将请求排队。1个命令对象和原先的请求发出者可以有不同的生命周期。换言之,原先的请求发出者可能已经不在了,而命令对象本身仍然是活动的。这时命令的接受者可以是在本地,也可以在网络的另外一个地址,命令对象可以在序列化之后传送到另外一台机器上去。
- 撰写本文考了不少博文,在此一并谢过。
《JAVA与模式》之命令模式- 转载时,请注明出处,这是人格的一种体现。
https://www.zybuluo.com/BertLee/note/854223- 能力有限,如有纰漏,请在评论区指出,老朽虽一把年纪,必当感激涕零,泪如雨下。