定义
- 将不同的请求封装成不同的对象。
适用场景
- 解决了应用程序中对象的职责以及他们之间的通信方式。
- 发送者和接收者完全解耦
- 需要抽象出等待执行的行为
优点
- 降低耦合
- 易扩展
- 下达一组命令
缺点
- 命令的无限扩展会增加类的数量,提高系统的复杂度。
代码
其实命令模式的核心就是将一个命令(方法)抽象成一个对象。
我们来选择一个场景
在我们军训的时候,会收到教官各式各样的命令,比如:
- 立正
- 稍息
我们就来拿代码模拟一下简单的命令模式吧。
命令接口(Command
)
/**
* 命令模式接口
*/
public interface Command {
/**
* 执行命令
*/
void execute();
}
只有一个简单的执行命令的方法。
教官对象(TrainingOfficer
)
/**
* 教官类
*/
public class TrainingOfficer {
/**
* 稍息
*/
public void haveRest() {
System.out.println("听我口令: 稍息");
}
/**
* 立正
*/
public void attention() {
System.out.println("听我口令 : 立正");
}
}
抽象稍息命令为对象(HaveRestCommand
)
/**
* 抽象出来的 消息命令
*/
public class HaveRestCommand implements Command{
private TrainingOfficer trainingOfficer;
public HaveRestCommand(TrainingOfficer trainingOfficer) {
this.trainingOfficer = trainingOfficer;
}
@Override
public void execute() {
trainingOfficer.haveRest();
}
}
将 教官对象 组合到抽象出来的命令类中.
抽象立正命令为对象(AttentionCommand
)
/**
* 立正抽象方法
*/
public class AttentionCommand implements Command{
private TrainingOfficer trainingOfficer;
public AttentionCommand(TrainingOfficer trainingOfficer) {
this.trainingOfficer = trainingOfficer;
}
@Override
public void execute() {
trainingOfficer.attention();
}
}
同上。
UML类图
测试
public class CommandTest {
public static void main(String[] args) {
TrainingOfficer trainingOfficer = new TrainingOfficer();
HaveRestCommand haveRestCommand = new HaveRestCommand(trainingOfficer);
AttentionCommand attentionCommand = new AttentionCommand(trainingOfficer);
//教练抽风经常多次稍息立正我们就把这些命令封装成一组
List<Command> commandList = new ArrayList<>();
commandList.add(haveRestCommand);
commandList.add(attentionCommand);
commandList.add(haveRestCommand);
commandList.add(attentionCommand);
for (Command command : commandList) {
command.execute();
}
}
}
结果
听我口令: 稍息
听我口令 : 立正
听我口令: 稍息
听我口令 : 立正
简单的命令模式已经演示完了,核心就是方法抽象。
其他开源
在spring cloud中的 熔断器 Hystrix
中 在执行降级方法时,我们就使用了命令模式
/**
* Convenience class for implementing feign fallbacks that return {@link HystrixCommand}.
* Also useful for return types of {@link rx.Observable} and
* {@link java.util.concurrent.Future}. For those return types, just call
* {@link FallbackCommand#observe()} or {@link FallbackCommand#queue()} respectively.
*
* @param <T> result type
* @author Spencer Gibb
*/
public class FallbackCommand<T> extends HystrixCommand<T> {
private T result;
public FallbackCommand(T result) {
this(result, "fallback");
}
// 省略部分代码
@Override
protected T run() throws Exception {
return this.result;
}
}
我们可以看到通过 对应抽象出来的业务中的降级命令类,执行run()
来降级。
小结
命令模式还是比较常见的设计模式,希望我能在具体的业务或功能上选择合适的设计模式。大家一起加油。