命令模式介绍
命令模式将需要执行的命令进行封装,请求方发送请求,接收方收到请求后执行请求,命令模式使请求者和接收者不用关心怎么调用和执行,只需要执行即可,屏蔽了实现,使请求方和接收方彻底的解耦,现实中也随处可见命令模式的使用,比如我们使用的电视机,我们只需要按下遥控器的按钮,便可以实现开关机,换台,调声音等,我们使用的空调,电磁炉,电饭煲也是如此,并不需要我们去将这根线和那根线结合,而是按相应的按钮即可。
命令模式中已经带了命令二字,现实生活中,老板命令我去加班,我就加班,老板命令我倒茶,我就倒茶,这有点把自己说成工具人的意思,但是确实是这个样子的,不过话又说回来了,不是工具人是什么啊
,老板的吩咐就是一句指令,我按照要求去做就得了,我们在操作Linux系统的时候,也是发出一条一条的指令,但是我们并不需要去关心它怎么执行,下面我们用一个案例来实现命令模式。
实现命令模式
我们现在来实现一个电饭煲的基本功能,开,关,煮饭,当然还有其它的很多功能,比如煮粥这些,都一样,这里我们以这三个为例。
定义一个命令的接口IRiceCookerCmd,后续所有的具体命令都要实现它
代码语言:javascript复制//电饭煲命令
public interface IRiceCookerCmd {
void execute();
}
编写打开电饭煲命令接口OpenRiceCookerCmd
代码语言:javascript复制//打开电饭煲命令
public class OpenRiceCookerCmd implements IRiceCookerCmd {
private final RiceCookerReceiver receiver = new RiceCookerReceiver();
@Override
public void execute() {
receiver.open();
}
}
关闭电饭煲命令接口CloseRiceCookerCmd
代码语言:javascript复制//关闭电饭煲命令
public class CloseRiceCookerCmd implements IRiceCookerCmd {
private final RiceCookerReceiver receiver = new RiceCookerReceiver();
@Override
public void execute() {
receiver.close();
}
}
煮饭命令CookRiceCmd
代码语言:javascript复制//煮饭命令
public class CookRiceCmd implements IRiceCookerCmd {
private final RiceCookerReceiver receiver = new RiceCookerReceiver();
@Override
public void execute() {
receiver.cookRice();
}
}
编写接收者RiceCookerReceiver ,接收者是真正执行命令的对象
代码语言:javascript复制public class RiceCookerReceiver {
private static boolean flag = false;
public void open(){
flag = true;
System.out.println("open it");
}
public void close(){
flag = false;
System.out.println("close it");
}
public void cookRice(){
if (flag)
System.out.println("start cooking rice");
else
System.out.println("please open the rice cooker , than cook rice");
}
}
编写调用者RiceCookerInvoker,调用者是真正发出命令和执行命令的对象,此处用一个List来存放命令,因为可能多个命令一起执行。
代码语言:javascript复制public class RiceCookerInvoker {
private final List<IRiceCookerCmd> cmds = new ArrayList<>();
public void addCmd(IRiceCookerCmd riceCookerCmd){
cmds.add(riceCookerCmd);
}
public void executeCmd(){
cmds.forEach(IRiceCookerCmd::execute);
cmds.clear();
}
}
客户端调用,我们只需要创建出对应的操作命令(电饭煲的按钮),然后便可完成相应的操作,如下我们按电饭煲开机按钮,然后按电饭煲煮饭按钮。
代码语言:javascript复制public class Client {
public static void main(String[] args) {
IRiceCookerCmd openRiceCookerCmd = new OpenRiceCookerCmd();
IRiceCookerCmd cookerCmd = new CookRiceCmd();
RiceCookerInvoker riceCookerInvoker = new RiceCookerInvoker();
riceCookerInvoker.addCmd(openRiceCookerCmd);
riceCookerInvoker.addCmd(cookerCmd);
riceCookerInvoker.executeCmd();
}
}
下面我们关闭电饭煲
代码语言:javascript复制public class Client {
public static void main(String[] args) {
IRiceCookerCmd closeRiceCookerCmd = new CloseRiceCookerCmd();
RiceCookerInvoker riceCookerInvoker = new RiceCookerInvoker();
riceCookerInvoker.addCmd(closeRiceCookerCmd);
riceCookerInvoker.executeCmd();
}
}
经过上面的一系列操作,我们就能吃上香喷喷的米饭了,我们发现,上面的代码中涉及很多部分,命令接口IRiceCookerCmd ,它是用来声明执行的方法,命令接口实现对象,如CookRiceCmd,CloseRiceCookerCmd ,但是具体命令并不是由它来做的,它内部会维护一个接收者,并且调用接收者来做实际的操作,接收者Receiver,它是真正执行命令的对象,调用者Invoker,它接收客户端的命令,并发起请求,客户端Client,它是命令的发起者,比如我按下电饭煲的开关按钮,我就是Client。
我们思考一下,其实命令接口实现对象位于Invoker和Receiver中间,它不做具体的实现,只是起到一个中间衔接的作用,这样就解耦了Invoker和Receiver。
命令模式的应用场景
我们在软件开发过程中,如果觉得某一个功能的每个请求都是一个命令,那么就可以考虑使用命令模式。
命令模式的优点
1.系统的扩展性好,如果有新的命令加入,则编写对应的命令实现类即可。
2.通过引入命令接口,降低系统的耦合度。
命令模式的缺点
如果具体的命令实现类过多,会增加系统的复杂度。
今天的分享就到这里,感谢你的观看,我们下期见。