行为型之命令模式
序言
命令模式把发出命令的责任和执行命令的责任分隔开,分别委托给不同的对象。
每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。
命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
使用命令模式会导致系统增加过度的具体命令类,使得其实现不切合实际。
命令模式涉及到5个角色,分别是:
- 命令角色:接口或者抽象类,抽象方法包含了命令的执行操作
- 具体命令角色:类,实现命令的执行方法,调用接受者的相应操作
- 请求者角色:类,负责调用命令的执行请求,相关的方法,叫行动方法
- 接受者角色:类,负责具体实施和执行1个请求,相关的方法,叫行动方法
命令模式
电视机会有开机,关机,换台的基本命令操作,我们不需要知道其内部实现,在这里我们是客户端,而电视机可以被看做命令接受者,遥控器则可以被看做是命令请求者,我们只需要和请求者打交道即可。
命令模式的结构如下图:
/**
* 命令接受者-电视机
*/
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 {
@Test
public 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个命令对象和原先的请求发出者可以有不同的生命周期。换言之,原先的请求发出者可能已经不在了,而命令对象本身仍然是活动的。这时命令的接受者可以是在本地,也可以在网络的另外一个地址,命令对象可以在序列化之后传送到另外一台机器上去。
后记
- 撰写本文考了不少博文,在此一并谢过。
《JAVA与模式》之命令模式- 转载时,请注明出处,这是人格的一种体现。
https://www.zybuluo.com/BertLee/note/854223- 能力有限,如有纰漏,请在评论区指出,老朽虽一把年纪,必当感激涕零,泪如雨下。