命令模式


命令模式

命令模式是一种行为型设计模式,它将请求封装成对象,以便在不同的请求、日志或事务中参数化其他对象,并支持可撤销操作。

适用场景

  • 当需要将请求、操作或行为放入队列中、记录日志、支持撤销等功能时,可使用命令模式;
  • 当需要以不同的参数来调用相同方法时,可使用命令模式;
  • 当需要执行一组操作,而不在意具体的执行过程时,可使用命令模式。

示例

我们以电视机为例来说明命令模式的实现。

假设我们有一个电视机类,有打开电视、关闭电视、调高音量和调低音量四个方法。现在需要将这四个操作封装成命令对象,支持队列、日志和可撤销操作,我们按照以下步骤来实现命令模式:

定义命令接口

public interface Command {
    void execute();
    void undo();
}

命令接口定义了两个方法,execute()方法用于执行命令,undo()方法用于撤销命令。

实现具体命令类

public class TurnOnCommand implements Command {
    private TV tv;
    public TurnOnCommand(TV tv) {
        this.tv = tv;
    }
    public void execute() {
        tv.turnOn();
    }
    public void undo() {
        tv.turnOff();
    }
}

public class TurnOffCommand implements Command {
    private TV tv;
    public TurnOffCommand(TV tv) {
        this.tv = tv;
    }
    public void execute() {
        tv.turnOff();
    }
    public void undo() {
        tv.turnOn();
    }
}

public class VolumeUpCommand implements Command {
    private TV tv;
    public VolumeUpCommand(TV tv) {
        this.tv = tv;
    }
    public void execute() {
        tv.volumeUp();
    }
    public void undo() {
        tv.volumeDown();
    }
}

public class VolumeDownCommand implements Command {
    private TV tv;
    public VolumeDownCommand(TV tv) {
        this.tv = tv;
    }
    public void execute() {
        tv.volumeDown();
    }
    public void undo() {
        tv.volumeUp();
    }
}

定义了四个具体命令类,分别对应四个操作。

实现命令调用者

public class RemoteControl {
    private List<Command> commandQueue = new ArrayList<>();
    public void press(Command command) {
        command.execute();
        commandQueue.add(command);
    }
    public void undo() {
        if (commandQueue.size() > 0) {
            Command command = commandQueue.get(commandQueue.size() - 1);
            command.undo();
            commandQueue.remove(command);
        }
    }
}

命令调用者具有press()undo()两个方法,press()方法用于执行命令,同时将命令添加到命令队列中;undo()方法用于撤销命令,从命令队列中取出最后一个命令并执行其undo()方法。

客户端使用

TV tv = new TV();
RemoteControl control = new RemoteControl();
control.press(new TurnOnCommand(tv));
control.press(new VolumeUpCommand(tv));
control.press(new VolumeUpCommand(tv));
control.press(new VolumeDownCommand(tv));
control.undo();

客户端使用时,创建电视机实例和遥控器实例,然后按照需要执行命令和撤销命令。

总结

使用命令模式,可以将复杂的操作封装成命令,从而实现队列、日志和撤销等功能,同时也符合面向对象的设计原则。但是,命令模式会增加系统的复杂度和代码量,需要权衡利弊后再做决定。