当前位置:首页 > Java

java如何撤销

2026-03-20 06:07:45Java

撤销操作的基本方法

在Java中实现撤销功能通常依赖于设计模式中的命令模式(Command Pattern)。核心思想是将操作封装为对象,记录操作的历史记录,便于回退。

定义一个抽象命令接口:

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

具体命令实现需保存操作前的状态:

public class ConcreteCommand implements Command {
    private Receiver receiver;
    private Object previousState;

    public void execute() {
        previousState = receiver.getState(); // 保存状态
        receiver.action();
    }

    public void undo() {
        receiver.setState(previousState); // 恢复状态
    }
}

历史记录管理

使用栈结构存储命令历史:

public class CommandHistory {
    private Stack<Command> history = new Stack<>();

    public void push(Command c) {
        history.push(c);
    }

    public Command pop() {
        return history.pop();
    }

    public boolean isEmpty() {
        return history.isEmpty();
    }
}

调用示例:

CommandHistory history = new CommandHistory();
Command cmd = new ConcreteCommand(receiver);

cmd.execute();   // 执行操作
history.push(cmd); // 记录

// 撤销操作
if (!history.isEmpty()) {
    history.pop().undo();
}

多级撤销实现

扩展历史记录管理支持多步撤销:

public class MultiLevelHistory {
    private Stack<Command> undoStack = new Stack<>();
    private Stack<Command> redoStack = new Stack<>();

    public void execute(Command cmd) {
        cmd.execute();
        undoStack.push(cmd);
        redoStack.clear(); // 新操作后清空重做栈
    }

    public void undo() {
        if (!undoStack.isEmpty()) {
            Command cmd = undoStack.pop();
            cmd.undo();
            redoStack.push(cmd);
        }
    }

    public void redo() {
        if (!redoStack.isEmpty()) {
            Command cmd = redoStack.pop();
            cmd.execute();
            undoStack.push(cmd);
        }
    }
}

状态快照方案

对于复杂对象,可采用备忘录模式(Memento Pattern)保存完整状态:

public class Originator {
    private String state;

    public Memento save() {
        return new Memento(state);
    }

    public void restore(Memento m) {
        state = m.getState();
    }

    // Memento为内部类
    public static class Memento {
        private final String state;
        private Memento(String state) {
            this.state = state;
        }
        private String getState() {
            return state;
        }
    }
}

使用示例:

Originator originator = new Originator();
Stack<Originator.Memento> history = new Stack<>();

// 保存状态
history.push(originator.save());

// 恢复状态
originator.restore(history.pop());

事务性撤销

对于数据库操作等场景,需结合事务管理:

java如何撤销

try {
    Connection conn = DriverManager.getConnection(DB_URL);
    conn.setAutoCommit(false); // 关闭自动提交

    // 执行SQL操作
    Statement stmt = conn.createStatement();
    stmt.executeUpdate("INSERT INTO table VALUES (...)");

    // 用户触发撤销
    conn.rollback(); // 回滚事务
} catch (SQLException e) {
    e.printStackTrace();
}

标签: java
分享给朋友:

相关文章

java如何下载

java如何下载

下载Java的步骤 访问Oracle官方网站或OpenJDK项目页面下载Java开发工具包(JDK)。Oracle JDK适用于商业用途,OpenJDK为开源版本。 打开浏览器,进入Oracle J…

java如何输入字符串

java如何输入字符串

使用 Scanner 类 在 Java 中,可以通过 java.util.Scanner 类来输入字符串。以下是一个示例代码: import java.util.Scanner; public c…

java如何处理高并发

java如何处理高并发

Java处理高并发的方法 使用多线程和线程池 Java的java.util.concurrent包提供了线程池(如ThreadPoolExecutor)和并发工具类(如CountDownLatch、C…

java版本如何查看

java版本如何查看

查看Java版本的命令行方法 在命令行或终端中运行以下命令可以查看当前安装的Java版本: java -version 输出示例: java version "1.8.0_301" Java(TM…

如何阅读java源码

如何阅读java源码

阅读Java源码的方法 选择合适的源码项目 初学者建议从JDK核心类库(如java.lang、java.util)或知名开源项目(如Spring、Guava)入手。选择文档完善、社区活跃的项目能降低理…

win7如何配置java环境变量

win7如何配置java环境变量

下载并安装Java 从Oracle官网下载适合的Java Development Kit (JDK)安装包,选择与系统位数(32位或64位)匹配的版本。运行安装程序,按照提示完成安装,默认路径通常为C…