一、引言
阳光明媚的一个周末。
上一章讲了模板方法设计模式,今天小编继续来说命令设计模式,也是行为型设计模式的一种~~~~
二、命令模式基本介绍
所谓命令模式,就是下达命令,最后有人执行命令。
大家想想古代打战的时候,将军下达命说,明天需要攻下某某某山头。
那么将军就找来了参谋长,这个时候参谋长得知了将军的意思,参谋长就找来每个军营的负责人,说一营、二营全部人员明天出发某某某山头。
你看将军其实他并不知道是哪个具体营的士兵大战,中间通过了这个参谋长来给军营的人沟通。
命令模式(Command Pattern)思想也是如此,我们经常需要向某些对象发送请求,但是不知道到请求的接收者是谁。在命令模式中,会将一个请求或者说一个命令封装成为一个对象,我们只需要在程序运行时指定具体的请求接收者即可。更加通俗的来说,将军发布命令,参谋长得知命令通知士兵,士兵具体执行该命令,由此可见,命令模式使得请求的发送者(将军)与请求的接收者(士兵)消除彼此之间的耦合度,让对象之间的调用更加灵活,实现解耦。
三、命令模式案例演示
呐呐呐呐呐呐么,就以刚刚举例打战的案例来使用具体代码实现。
打战就肯定要有士兵,所以我们先来创建一个士兵的类,并且定义士兵所能做的事。士兵也是最后命令的执行者
/**
* @Auther: IT贱男
* @Date: 2019/12/13 10:40
* @Description: 定义士兵动作,命令执行者
*/
public class Robot {
private String name;
public Robot(String name) {
this.name = name;
}
/**
* 士兵开火
*/
public void fire() {
System.out.println(this.name + "正在开火......");
}
/**
* 士兵停火
*/
public void stop() {
System.out.println(this.name + "停止开火......");
}
}
定义抽象的命令,可以定义命令的行为,比如执行命令,撤销命令。 有抽象的命令,那么当然就肯定有具体执行命令对象。文章上面有说,会将一个请求或者说一个命令封装成为一个对象,那么既一个命令就是一个对象。接下来我们还要创建开火和停止开火的两个命令对象。
/**
* @Auther: IT贱男
* @Date: 2019/12/12 13:58
* @Description: 抽象命令者
*/
public interface Command {
/**
* 执行命令
*/
void execute();
}
/**
* @Auther: IT贱男
* @Date: 2019/12/13 10:44
* @Description: 开火命令,将命令请求封装成对象
*/
public class RobotFireCommand implements Command {
// 聚合士兵,士兵是具体执行者
private Robot robot;
public RobotFireCommand(Robot robot) {
this.robot = robot;
}
@Override
public void execute() {
// 调用士兵的开火方法
robot.fire();
}
}
/**
* @Auther: IT贱男
* @Date: 2019/12/13 10:47
* @Description: 停止开火命令,将命令请求封装成对象
*/
public class RobotStopCommand implements Command {
private Robot robot;
public RobotStopCommand(Robot robot) {
this.robot = robot;
}
@Override
public void execute() {
robot.stop();
}
}
士兵和命令都有了,那么这个时候常参谋长就该登场了,参谋长就可以接收命令,以及通知执行命令。
/**
* @Auther: IT贱男
* @Date: 2019/12/13 10:48
* @Description: 参谋长的角色 负责接受命令,以及通知士兵执行
*/
public class Staff {
// 命令集合
private List<Command> commandList = new ArrayList<>();
// 添加命令
public void addCommand(Command command) {
commandList.add(command);
}
// 执行命令
public void excuteCommands() {
for (Command command : commandList) {
command.execute();
}
commandList.clear();
}
}
/**
* @Auther: IT贱男
* @Date: 2019/12/13 10:59
* @Description:
*/
public class Client {
public static void main(String[] args) {
// 创建一个士兵
Robot robot = new Robot("张三");
RobotFireCommand fireCommand = new RobotFireCommand(robot);
// 这个时候参谋长得知了将军的消息,要开火了
Staff staff = new Staff();
staff.addCommand(fireCommand);
// 下达命令给士兵
staff.excuteCommands();
// 这个时候敌人消灭了,下命令停止开火
RobotStopCommand stopCommand = new RobotStopCommand(robot);
staff.addCommand(stopCommand);
// 下达命令给士兵
staff.excuteCommands();
}
}
四、命令模式使用注意细节
命令模式最主要的作用就是把请求的调用者和请求执行者进行解耦,每一个具体命令就是单独的一个对象,缺点也就很显而易见了,如果有很多命令就会导致类爆炸的问题。
其实一个严谨的命令模式,往往还需要支持撤销的功能,本章小编就没有演示了,因为单单在命令模式中使用撤销,小编感觉稍微有点点的鸡肋。 命令模式可以和备忘录模式进行组合使用,这样备忘录可以记录上一次的操作,命令模式就可以撤销上一次的操作了。
总的来说,命令模式还是比较好理解的。