Java设计模式:命令模式的介绍及代码演示

83 阅读4分钟

命令模式介绍

命令模式是指,将需要执行的命令封装成一个对象,对象在程序中可以被任意传递,而不需要关心命令是被谁执行的,通过这个命令对象实现了命令请求和命令接收的解耦。打个比方说,去餐厅吃饭,服务员给了一个菜单,客人选择好菜品,服务员将菜单传递给厨师就好,客人并不知道是哪位厨师为自己烹饪食物,在这个例子中,菜单就是被封装的命令对象,服务员是命令的调度者,而厨师就是最终执行命令的人。

image.png

上面的餐厅点餐示例中,菜单就表示可以被自由传递的命令对象,它由服务员也就是命令调度者负责调度命令的执行,具体的命令执行者为厨师。

代码示例

现在有一个需要,要实现通过命令获取当前的国家和时间信息。想要实现这个需求,首先要创建一个具体的获取国家和时间的命令执行者类,然后创建两个命令对象,一个表示获取国家信息命令,另一个表示获取时间信息命令,最后创建一个调度者类,定义如何执行这两条命令。

创建具体的命令执行类

/**
 * 执行命令的对象
 */
public class Receiver {
    /**
     * 当前日期
     */
    public void date() {
        System.out.println(new Date());
    }

    /**
     * 当前国家
     */
    public void country() {
        System.out.println("中国");
    }
}

执行类包含获取当前的国家和时间的两个方法。

创建抽象命令类

/**
 * 命令接口
 */
public interface Command {
    /**
     * 执行命令抽象方法
     */
    void execute();
}

抽象命令类定义了用来调用执行类中命令的方法

创建具体的命令类

/**
 * 具体命令类-当前日期
 */
public class CommandDate implements Command{
    private Receiver custom; 

    public CommandDate(Receiver custom) {
        this.custom = custom;
    }

    @Override
    public void execute() {
        custom.date();
    }
}
/**
 * 具体命令类-当前国家
 */
public class CommandCountry implements Command{
    private Receiver custom;

    public CommandCountry(Receiver custom) {
        this.custom = custom;
    }

    @Override
    public void execute() {
        custom.country();
    }
}

上面两个类中包含了命令执行对象,并在各自的execute方法中调用了执行对象的具体命令。

创建一个命令调度者

/**
 * 命令调度
 */
public class Call {
    private List<Command> list = new ArrayList<>();

    /**
     * 获取命令
     * @param command 命令对象
     */
    public void takeCommand(Command command) {
        list.add(command);
    }

    /**
     * 执行命令
     * @param command
     */
    public void implCommand() {
        list.forEach(c -> {
            c.execute();
        });
    }
}

命令调度类中包含命令对象的集合,用来存储多个命令对象,takeCommand()方法用来添加新的命令对象到集合中,implCommand()方法则是实现依次执行命令集合中所有的命令。拿餐厅点餐例子来说,takeCommand()就像是客户在点菜,implCommand()方法就像是厨师根据菜单依次烹饪食物。当然这里的代码案例实现的是依次执行获取时间和国家的两个命令。

测试命令模式

public class test_01 {
    public static void main(String[] args) throws InterruptedException {
        //创建命令执行对象
        Receiver receiver = new Receiver();
        //创建具体命令对象
        Command date = new CommandDate(receiver);
        Command country = new CommandCountry(receiver);
        //创建命令调度对象
        Call call = new Call();
        //添加对象到命令列表
        call.takeCommand(date);
        call.takeCommand(country);
        //依次执行命令列表中的命令
        call.implCommand();
    }
}

第一步,创建具体的命令执行对象。第二步,创建具体的命令对象。第三步,创建命令调度对象,将命令添加到命令列表并依次执行所有命令。

运行结果:

image.png

总结

命令模式实现了通过命令对象将命令的请求和执行解耦,命令对象可以自由的在程序中被传递,命令请求者不需要知道命令最终被谁处理,实现了将命令以参数的形式进行传递。并且在命令模式中,因为命令是独立存在的,所以在需要添加新的命令时,很容易扩展,提高了程序的灵活性。