JAVA 实现Undo/Redo(撤销/恢复)一
Undo/Redo是软件的一个常用功能,Java 在swing中提供了Undo包, 提供了对JTextComponent组件的Undo/Redo支持。但是除了文本处理以外的Undo/Redo一般要自己实现,而且即使是文本处理的Undo/Redo, 好像也有些不足,例如输入时Undo/Redo是一个一个字符的,如果要做到WORD的一次一串字符撤销/恢复,也要自己实现。最近,研究了一下Undo包, 发现它的类还是比较复杂的。那么,能用简单的方法实现自己的Undo/Redo系统吗?网上的答案一般是用Command模式, 但很难看到简单易懂的实现方式。这里,本文试图通过自己的理解实现一个简单的Undo/Redo系统。
一, Undoable和Command接口
要实现Undo/Redo功能,要实现Undoable和Command接口。
public interface Undoable {
public void undo();
public void redo();
public boolean canUndo();
public boolean canRedo();
}
public interface Command {
public void execute();
}
二, UndoableCommand抽象类
在Undoable和Command接口基础上封装一个抽象类,为了简单起见,没有让它显式implements Undoable和Command接口。
UndoableCommand类的主要功能:
封装了一个boolean 变量 canUndo, 因为一个Command只有canUndo和canRedo两种状态,当Undo和Redo的时候要完成相应boolean值的切换。
Undo后只能Redo, Redo后只能Undo, 错误的调用会抛出异常。
提供抽象方法 command()和restore(), 由子类来实现Undo/Redo的逻辑。
提供boolean方法canAppendWith(UndoableCommand other), 当一些Command需要一起Undo,Redo时由子类override
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
public abstract class UndoableCommand {
protected boolean canUndo;
protected abstract void command();
protected abstract void restore();
public void execute() {
command();
setCanUndo(true);
}
protected void unExecute() {
restore();
setCanUndo(false);
}
public void undo() {
if (!canUndo()) {
throw new CannotUndoException();
}
unExecute();
}
public void redo() {
if (!canRedo()) {
throw new CannotRedoException();
}
execute();
}
public boolean canUndo() {
return canUndo;
}
public boolean canRedo() {
return !canUndo;
}
protected void setCanUndo(boolean canUndo) {
this.canUndo = canUndo;
}
protected boolean canAppendWith(UndoableCommand other) {
return false;
}
}