一、定义
命令模式(Command Pattern):是一种数据驱动的设计模式。其将具体的执行(命令)封装成对象,通过调度器传递给执行者,从而实现请求者和执行者之间的解耦。
上述定义是不是很难理解?这些严谨官方的定义,常见于汇报或者书籍中,不利于快速理解。实际上设计模式的命名都是很考究的,从名称便可以理解其要解决的问题和应用场景。下面我们换种定义,加深一下理解:
命令模式(Command Pattern):顾名思义,就是A命令B执行某些任务。那么怎么执行呢?A取出一个锦囊(命令),让其秘书交给B,并告知B要依计行事。这样A和B素未谋面,但是事已完成(低耦合)。结构图如下:
二、角色介绍
上述的执行过程中定义了多位参与者,下面介绍这些参与者的职能。
1、命令:即上文中的锦囊。命令在各个角色中流转,是最重要的通信工具。
2、执行者:命令最终的接受者,将由执行者完成具体任务,完成后命令便被处理,不再传递。
3、请求者:命令的发起方,只提需求,不关心谁完成,怎么完成。
3、调度器:收集所有的命令并将命令传递给执行者,起到桥梁作用。
此时再理解官方的定义是不是很好理解了,所谓命令模式就是:
一种数据驱动的设计模式。其将具体的执行(命令)封装成对象,通过调度器传递给执行者,从而实现请求者和执行者之间解耦。
三、优缺点
优点在上述的定义中也都有所体现,主要有以下两点
1:低耦合。其降低了请求者和执行者之间的耦合,使得系统更加灵活。
2:易扩展。当需要增加某些命令、执行对象时,便于扩展,无需修改现有逻辑。
缺点是引入了过多的角色,造成命令类的数量增加,但是在优点面前,部分缺点是可以忽略的,有舍方有得。
四、案例分析
下面以智能家居的声控系统为例,使用命令模式设计一个j简单的智能控制系统。分析此案例可以轻松发现请求者是家居主人,执行者是接入智能系统的家电,如电灯、扫地机器人、空调等。下面我们逐一设计,部分代码以伪代码实现。
首先先创建单个智能家电抽象类和实体类。
public interface Excute {
void open();
void close();
}
public class Light implements Excute {
@Override
public void open() {
//开灯
}
@Override
public void close() {
//关灯
}
}
public class AirConditioner implements Excute {
@Override
public void open() {
//开空调
}
@Override
public void close() {
//关空调
}
}
之后创建命令类,此处只创建开灯和关灯的命令。
public interface Command {
void diAction();
}
public class OpenLightCommand implements Command {
private Excute excute;
public OpenLightCommand(Excute excute) {
this.excute = excute;
}
@Override
public void diAction() {
if (excute != null) {
excute.open();
}
}
}
public class CloseLightCommand implements Command {
private Excute excute;
public CloseLightCommand(Excute excute) {
this.excute = excute;
}
@Override
public void diAction() {
if (excute != null) {
excute.close();
}
}
}
然后创建调度器,构建主人和家电之间的桥梁。
public class CommandManager() {
private final Light light = new Light();
private static final OpenLightCommand openLightCommand = new OpenLightCommand(light);
private static final CloseLightCommand closeLightCommand = new CloseLightCommand(light);
public static void enterCommand(String voiceInput) {
if ("openLight".equals(voiceInput)) {
openLightCommand.diAction();
} else if ("closeLight".equals(voiceInput)) {
closeLightCommand.diAction();
}
}
}
最后,主人只需要输入语音命令即可控制
CommandManager.enterCommand("openLight");
上述便是设计模式的命令模式,其核心要义就是将请求封装成对象,实现请求者和执行者之间解耦。关注我将持续分享设计模式的开发技巧。