定义: 将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
先转换概念: 将一个命令封装为一个对象,使发出命令的对象和执行命令的对象分割开。
提取关键词: 命令=对象,发出命令的对象,执行命令的对象。需要3个对象。
如上所示,定义了三个对象,扩展了两个具体命令。
命令发送方
/**
* @author lw
* @date 2022/3/31 0031
* @description 短信调用者(发出命令方
*/
public class SmsInvoker {
//一系列命令
List<SmsCommand> commands = new ArrayList<>();
SmsInfo smsInfo = new SmsInfo();
public void executeCommand(){
for (SmsCommand command : commands) {
command.execute(smsInfo);
}
//命令执行完毕后清空
this.commands.clear();
}
}
命令发送方中定义了List,可以放入一系列的命令,他只知道使用SmsCommand调用,并不知道这个调用会让谁执行。
命令
public interface SmsCommand {
void execute(SmsInfo info);
}
public class SmsCheckCommand implements SmsCommand{
SmsReceive smsReceive;
public SmsCheckCommand(SmsReceive smsReceive){
this.smsReceive = smsReceive;
}
@Override
public void execute(SmsInfo info) {
smsReceive.checkContent(info);
}
}
public class SmsSendCommand implements SmsCommand{
SmsReceive smsReceive;
public SmsSendCommand(SmsReceive smsReceive){
this.smsReceive = smsReceive;
}
@Override
public void execute(SmsInfo info) {
smsReceive.send(info);
}
}
这里定义了所有执行者都是SmsReceive,其实也可以分开成多个命令执行者,或者这个命令是由一系列的条件组成。
每一条命令可以是一系列的原子操作,也可以是组合操作,就看业务需求如何。
执行者
/**
* @author lw
* @date 2022/3/31 0031
* @description 短信执行者(执行命令方)
*/
public class SmsReceive {
public void send(SmsInfo smsInfo){
System.out.println("发送短信:"+smsInfo.content);
}
public void checkContent(SmsInfo smsInfo){
System.out.println("检查内容:"+smsInfo.content);
}
}
调用者
SmsInvoker invoker = new SmsInvoker();
SmsReceive receive = new SmsReceive();
//内容检查
SmsCheckCommand checkCommand = new SmsCheckCommand(receive);
invoker.commands.add(checkCommand);
invoker.executeCommand();
//短信发送
SmsSendCommand sendCommand = new SmsSendCommand(receive);
invoker.commands.add(sendCommand);
invoker.executeCommand();
如果单独看上面的例子,感觉命令模式很无用,多了好多Command类,而且还需要注意顺序。
但是看下面这个Service,sendSms是一个命令体,发送短信是由一系列其他操作组合而成,这也可以看成是一个简单命令模式。
public void sendSms(SmsInfo smsInfo){
this.checkContent(smsInfo);
this.send(smsInfo);
}
public void checkContent(SmsInfo smsInfo){
System.out.println("检查内容:"+smsInfo.content);
}
public void send(SmsInfo smsInfo){
System.out.println("发送短信:"+smsInfo.content);
}
命令模式并不用局限于定义一些Command类就是命令模式,虽然定义说将请求封装为一个对象,请求的发送者和执行者分开,但是如下图所示,调用sendSms()方法的就是命令发出者,这些子方法就是一个个执行者。
所谓的对象,并不一定是局限于一个个Class修饰的类,它也可以是方法。
总结
命令模式分三个对象: 命令发出者(Invoker),命令(Command)和命令执行者(Receive)