MST
星途 面试题库

面试题:Java命令模式下如何实现撤销操作

在Java命令模式的基础上,描述如何添加撤销(Undo)操作的功能。说明在设计过程中涉及到哪些关键类的修改或新增,并且提供核心代码片段来实现该功能。
12.3万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

关键类的修改或新增

  1. 命令接口(Command Interface)
    • 需要在命令接口中添加一个undo方法,用于执行撤销操作。
    public interface Command {
        void execute();
        void undo();
    }
    
  2. 具体命令类(Concrete Command Classes)
    • 每个具体命令类除了实现execute方法外,还需要实现undo方法。在undo方法中,通常需要反转execute方法所执行的操作。例如,如果execute方法是增加某个值,undo方法则减少该值。
    public class ConcreteCommand implements Command {
        private Receiver receiver;
        private int stateBeforeExecute;
    
        public ConcreteCommand(Receiver receiver) {
            this.receiver = receiver;
        }
    
        @Override
        public void execute() {
            stateBeforeExecute = receiver.getState();
            receiver.action();
        }
    
        @Override
        public void undo() {
            receiver.setState(stateBeforeExecute);
        }
    }
    
  3. 调用者类(Invoker Class)
    • 调用者类需要维护一个命令历史记录栈,以便在需要时能够取出最近执行的命令并调用其undo方法。
    import java.util.Stack;
    
    public class Invoker {
        private Stack<Command> commandStack = new Stack<>();
    
        public void executeCommand(Command command) {
            command.execute();
            commandStack.push(command);
        }
    
        public void undoLastCommand() {
            if (!commandStack.isEmpty()) {
                Command command = commandStack.pop();
                command.undo();
            }
        }
    }
    
  4. 接收者类(Receiver Class)
    • 接收者类可能需要提供一些额外的方法,以便具体命令类的undo方法能够反转操作。例如,提供获取和设置状态的方法,如上述ConcreteCommand类中用到的getStatesetState方法。
    public class Receiver {
        private int state;
    
        public void action() {
            state++;
        }
    
        public int getState() {
            return state;
        }
    
        public void setState(int state) {
            this.state = state;
        }
    }
    

核心代码示例

  1. 测试代码
    public class Main {
        public static void main(String[] args) {
            Receiver receiver = new Receiver();
            Command command = new ConcreteCommand(receiver);
            Invoker invoker = new Invoker();
    
            invoker.executeCommand(command);
            System.out.println("After execute, state: " + receiver.getState());
    
            invoker.undoLastCommand();
            System.out.println("After undo, state: " + receiver.getState());
        }
    }
    

在上述代码中,通过对命令模式中关键类的修改和新增,实现了撤销操作的功能。命令接口添加了undo方法,具体命令类实现了该方法以反转操作,调用者类维护命令历史记录栈来支持撤销操作,接收者类提供了必要的方法协助具体命令类完成撤销。