命令模式Command —— 我不认识你,但我可以命令你
命令模式的核心在于引入了命令类,通过命令类来降低发送者和接收者的耦合度,请求发送者只需指定一个命令对象,再通过命令对象来调用请求接收者的处理方法。
一、什么是命令模式?
命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。
命令模式包含如下角色:
-
Receiver接收者角色
命令接收者模式,命令传递到这里执行对应的操作。 -
Command命令角色
需要执行的命令都在这里声明 -
Invoker调用者角色
接收到命令,并执行命令,也就是命令的发动者和调用者
二、代码实现
抽象命令类:
public abstract class Command {
public abstract void execute();
}
具体命令类:
@AllArgsConstructor
public class ConcreteCommand extends Command{
private Receiver receiver;
@Override
public void execute() {
receiver.action();
}
}
调用者:
@AllArgsConstructor
public class Invoker {
private Command command;
public void call(){
command.execute();
}
}
抽象接收者:
public abstract class Receiver {
public abstract void action();
}
具体接收者1:
public class ConcreteReceiver01 extends Receiver{
@Override
public void action() {
Console.log("接收者【01】接到指令!开始行动!");
}
}
具体接收者2:
public class ConcreteReceiver02 extends Receiver{
@Override
public void action() {
Console.log("接收者【02】接到指令!开始行动!");
}
}
public class Client {
public static void main(String[] args) {
ConcreteReceiver01 concreteReceiver01 = new ConcreteReceiver01();
ConcreteCommand concreteCommand01 = new ConcreteCommand(concreteReceiver01);
Invoker invoker01 = new Invoker(concreteCommand01);
invoker01.call();
ConcreteReceiver02 concreteReceiver02 = new ConcreteReceiver02();
ConcreteCommand concreteCommand02 = new ConcreteCommand(concreteReceiver02);
Invoker invoker02 = new Invoker(concreteCommand02);
invoker02.call();
}
}
接收者【01】接到指令!开始行动!
接收者【02】接到指令!开始行动!
三、适用场景
优点:
- 类间解耦
- 调用者和接受者之间没有任何依赖关系
- 调用者实现的时候只需要调用Command抽象类的execute方法就行了
- 不需要了解到底是谁在执行
- 可扩展性
- Command的子类非常容易扩展,调用者Invoker和高层次的Client不产生严重的代码耦合
- 命令模式结合其他模式会更优秀
- 命令模式可以结合责任链模式,实现命令族解析任务
- 结合模板方法模式,则可以减少Command子类的膨胀问题。
缺点:
- 如果有N个命令,就需要N个Command的子类,类膨胀非常大
适用场景:
在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。
只要你认为是命令的地方就可以采用命令模式,例如,在GUI开发中,一个按钮的点击是一个命令,可以采用命令模式;模拟DOS命令的时候,当然也要采用命令模式;触发-反馈机制的处理等。