Bootstrap

【设计模式-行为型】命令模式

一、什么是命令模式

        什么是命令模式?就是字面理解,下命令,但是还不能这么快下定义,可以举一个例子来说明一下。好多电影里面经常会有一个神秘的杀手组织,他们只管要钱和目标。不管是谁的委托,经常有个大富豪,说“为了确保万无一失,无论多少钱,我要求派出江湖第一杀手”,他们可是把命令模式玩的飞起。就好像《这个杀手不太冷》中主角杀手莱昂接受任务和执行任务的过程。

        在电影中,莱昂(里昂)是一个职业杀手,他通过中间人接受任务,并执行任务。这个过程可以类比为命令模式,其中莱昂是“接收者”,中间人是“调用者”,而任务本身是“命令”。通过《这个杀手不太冷》中的场景,我们可以清晰地看到命令模式的核心优势。命令模式通过将请求封装为对象,使得请求的发起者和执行者之间解耦,提高了系统的灵活性和可扩展性。这种模式特别适用于需要动态执行命令(封装的请求)的场景。命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为一个对象,从而使用户可以用不同的请求对客户进行参数化。

二、为什么用命令模式   

  1. 解耦客户端和接收者:客户端(客户)不需要直接调用接收者(杀手)的业务方法,而是通过命令对象间接调用。杀手组织只接受命令,而不管命令的具体内容或发起者是谁。

  2. 支持可撤销操作:命令模式可以轻松实现命令的撤销和重做功能。具体命令类可以保存操作前的状态,以便在需要时恢复。

  3. 支持命令排队和日志记录:命令对象可以被存储在队列中,支持命令的排队执行。同时,命令对象可以被记录在日志中,便于后续的审计和恢复。

  4. 扩展性:命令模式支持动态添加新的命令,而不需要修改现有的代码。新的命令只需要实现命令接口即可。

三、命令模式示例

代码示例以及命令模式的角色解析

  1. Command(命令接口,定义任务统一行为):定义了执行操作的接口,所有具体命令类都实现这个接口。

    public interface Command {
        void execute();
    }
  2. ConcreteCommand(具体命令类,具体的任务):实现了命令接口,具体执行操作。它通常持有一个接收者对象,并调用接收者的业务方法来完成操作。

    public class KillCommand implements Command {
        private Hitman hitman;
        private String target;
    
        public KillCommand(Hitman hitman, String target) {
            this.hitman = hitman;
            this.target = target;
        }
    
        @Override
        public void execute() {
            hitman.kill(target);
        }
    }
  3. Receiver(接收者,杀手):实际执行操作的对象。具体命令类会调用接收者的业务方法来完成操作。

    public class Hitman {
        public void kill(String target) {
            System.out.println("杀手莱恩准备执行刺杀任务,任务目标: " + target);
        }
    }
  4. Invoker(调用者,杀手组织中间人):负责调用命令对象的执行方法。它通常持有一个命令对象,并在适当的时候调用命令对象的执行方法。

    public class Middleman {
        private Command command;
    
        public void setCommand(Command command) {
            this.command = command;
        }
    
        public void executeCommand() {
            command.execute();
        }
    }
  5. Client(客户端):创建具体命令对象,并将其与接收者关联。客户端将命令对象传递给调用者,调用者在适当的时候执行命令。

    public class Main {
        public static void main(String[] args) {
            // 创建接收者(杀手莱昂)
            Hitman hitman = new Hitman();
    
            // 创建具体命令对象(任务)
            Command killCommand = new KillCommand(hitman, "小女孩");
    
            // 创建调用者(中间人)
            Middleman middleman = new Middleman();
    
            // 设置命令并执行
            middleman.setCommand(killCommand);
            middleman.executeCommand();
        }
    }
    
    //输出
    杀手莱恩准备执行刺杀任务,任务目标: 小女孩
;