命令模式

181 阅读3分钟

摘要

命令模式是软件开发中的一种设计模式,它可以将请求封装成对象,从而使我们能够参数化不同的请求,将请求排队或记录日志,以及支持可撤销的操作。这篇文章将带你走进命令模式的世界,为你揭示为什么要使用命令模式,如何使用它以及它的优缺点。并且,我们将通过一段简单易懂的代码演示来巩固你的理解。

架构图

structure.png

为什么要使用命令模式

假设你是一名指挥官,你需要向你的士兵下达各种指令。有时你需要让士兵前进,有时你需要让士兵停下来,有时你甚至需要让士兵后退。如果没有命令模式,你将不得不直接告诉每个士兵要做什么。这是一项繁琐的工作。命令模式的出现解决了这个问题,它将每个指令封装成一个命令对象,你只需要简单地下达命令,而无需关心具体的执行细节。

如何使用命令模式

在命令模式中,有四个核心角色:命令接口具体命令调用者接收者。命令接口定义了命令的执行方法,具体命令实现了命令接口,并包含了执行具体指令的逻辑。调用者持有一个命令对象,并在需要的时候调用命令对象的执行方法。接收者是真正执行指令的对象。

命令模式的使用步骤

  1. 定义命令接口,包含命令的执行方法。
  2. 创建具体命令类,实现命令接口,并实现具体的指令逻辑。
  3. 创建接收者类,该类包含真正执行指令的逻辑。
  4. 创建调用者类,该类持有一个命令对象,并在需要的时候调用命令对象的执行方法。
  5. 在客户端代码中,创建具体命令对象、接收者对象和调用者对象,并将它们组装起来。

命令模式的优缺点

优点:

  1. 解耦:命令模式将请求发送者和接收者解耦,使得系统更加灵活,可扩展性更好。
  2. 可撤销操作:由于命令对象封装了请求,因此可以轻松实现操作的撤销和重做。
  3. 记录日志:命令模式可以记录操作日志,便于事后审计和回溯。
  4. 容易扩展:增加新的具体命令类和接收者类非常容易,无需修改现有代码。

缺点:

  1. 增加了类的数量:引入命令模式会增加额外的类,增加了代码的复杂度。
  2. 可能引入过多的小命令对象:在一些简单的场景中,可能会出现过多的小命令对象,影响性能。

代码演示

让我们通过一个有趣的例子来演示命令模式。假设你是一名餐厅的服务员,你需要下达各种指令给厨房的工作人员。 首先,我们来定义命令接口:

public interface Command {
    void execute();
}

接下来,我们创建具体命令类,比如炒菜、煮面等:

public class StirFryCommand implements Command {
    private Chef chef;

    public StirFryCommand(Chef chef) {
        this.chef = chef;
    }

    public void execute() {
        chef.stirFry();
    }
}

public class NoodleCookingCommand implements Command {
    private Chef chef;

    public NoodleCookingCommand(Chef chef) {
        this.chef = chef;
    }

    public void execute() {
        chef.cookNoodles();
    }
}

然后,我们创建接收者类Chef,实现具体的炒菜和煮面逻辑:

public class Chef {
    public void stirFry() {
        System.out.println("大厨正在炒菜...");
        // 具体的炒菜逻辑
    }

    public void cookNoodles() {
        System.out.println("大厨正在煮面...");
        // 具体的煮面逻辑
    }
}

最后,我们创建调用者类Waiter,持有一个命令对象,并在需要的时候调用命令对象的执行方法:

public class Waiter {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void notifyChef() {
        System.out.println("新的订单!");
        command.execute();
    }
}

现在,我们可以在客户端代码中使用命令模式了:

public class Client {
    public static void main(String[] args) {
        Chef chef = new Chef();
        Command stirFryCommand = new StirFryCommand(chef);
        Command noodleCookingCommand = new NoodleCookingCommand(chef);

        Waiter waiter = new Waiter();
        waiter.setCommand(stirFryCommand);
        waiter.notifyChef();

        waiter.setCommand(noodleCookingCommand);
        waiter.notifyChef();
    }
}

参考资料

命令模式