定义

将请求封装成对象,以便使用不同的请求、日志、队列等来参数化其他对象。命令模式也支持撤销操作。

角色

  • Command:定义命令的统一接口

  • ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。

  • Receiver:命令的实际执行者

  • Invoker:命令的请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制。

命令模式的本质就在于将命令进行封装,将发出命令的责任和执行命令的责任分开,使发送者只需要知道如何发送命令即可,不需要了解命令是如何实现的,甚至命令执行是否成功都不需要理会。同时命令模式使得请求也变成了一个对象,它像其他对象一样可以被存储和传递。

优缺点

优点:

  • 降低了系统耦合度

  • 新的命令可以很容易添加到系统中去。

缺点:

  • 使用命令模式可能会导致某些系统有过多的具体命令类。

实例

以遥控器操控电视机为例。

电视机:

/**
 * 电视机
 */
public class Television {

    public void open() {
        System.out.println("打开电视机......");
    }

    public void close() {
        System.out.println("关闭电视机......");
    }

    public void changeChannel() {

        System.out.println("切换电视频道......");
    }
}

命令接口

/**
 * 命令接口,为所有的命令声明一个接口。所有的命令都应该实现它
 */
public interface Command {
    void execute();
}

遥控器:

/**
 * 遥控器
 */
public class Controller {
    private Command openTVCommand;
    private Command closeTVCommand;
    private Command changeChannelCommand;

    public Controller(Command openTvCommand,Command closeTvCommand,Command changeChannelCommand){
        this.openTVCommand = openTvCommand;
        this.closeTVCommand = closeTvCommand;
        this.changeChannelCommand = changeChannelCommand;
    }

    /**
     * 打开电视剧
     */
    public void open(){
        openTVCommand.execute();
    }

    /**
     * 关闭电视机
     */
    public void close(){
        closeTVCommand.execute();
    }

    /**
     * 换频道
     */
    public void change(){
        changeChannelCommand.execute();
    }
}

具体按钮对象:

/**
 * 遥控器开机按钮
 */
public class OpenTvCommand implements Command {
    private Television tv;

    public OpenTvCommand() {
        tv = new Television();
    }


    @Override
    public void execute() {
        tv.open();
    }
}

/**
 * 遥控器调频按钮
 */
public class ChangeChannelCommand implements Command {
    private Television tv;

    public ChangeChannelCommand() {
        tv = new Television();
    }
    @Override
    public void execute() {
        tv.changeChannel();
    }
}


/**
 * 遥控器关机按钮
 */
public class CloseTvCommand implements Command {

    private Television tv;

    public CloseTvCommand() {
        tv = new Television();
    }
    @Override
    public void execute() {
        tv.close();
    }
}

测试:

public static void main(String[] args) {
    Command openCommand, closeCommand, changeCommand;

    openCommand = new OpenTvCommand();
    closeCommand = new CloseTvCommand();
    changeCommand = new ChangeChannelCommand();

    Controller control = new Controller(openCommand, closeCommand, changeCommand);
    // 打开电视机
    control.open();
    // 换频道
    control.change();
    // 关闭电视机
    control.close();
}

控制台输出:

打开电视机......
切换电视频道......
关闭电视机......
02-13 03:00