Java中实现Undo和Redo操作

可撤销操作:
每一个可以撤销的操作都是一个UndoableEdit对象(实质是实现了UndoableEdit接口),对于自定义的可撤消操作,可以直接实现UndoableEdit接口,也可以继承AbstractUndoableEdit对象。AbstractUndoableEdit已经帮助我们进行了基本的底层实现。

自定义UndoableEdit对象的一般的实现为:
构造函数:接收执行操作必要的参数(也许还要保存初始状态,当然,放在execute()里面似乎更合理一些)
execute() :执行操作,保存初始状态以便执行undo操作。这个函数不是UndoableEdit接口的一部分,但因为redo一般就是execute(),所以一起放在UndoableEdit对象里面。
undo():撤销操作,根据保存的初始状态进行还原。
redo():重做操作,调用execute。
注意,如果是继承于AbstractUndoableEdit,在undo(),redo()中要各自先调用一下super.undo()和super.redo(),这两个函数会更新底层的boolean值,用于标记AbstractUndoableEdit的执行状态,在UndoManager中会用到。
getPresentationName():对于操作的描述。

然后,UndoManager。
对于可撤销操作的执行和管理需要用到UndoManager,它负责undo/redo的执行,更新内部队列。
每执行一次UndoableEdit操作,undoManager.addEdit(edit)将它加入到undoManager维护的一个操作队列中。
要撤销或重做某次操作只需要undoManager.undo()或者undoManager.redo()就行了。

由于每执行一次UndoableEdit操作,需要更新undo、redo按钮或菜单。那么就用一个UndoableEditSupport 来进行管理。

基本的流程是:
每次产生一个UndoableEdit对象,执行对象操作。
调用UndoableEditSupport.postEdit(edit)将它传递给UndoableEditSupport对象。
这会触发添加在UndoableEditSupport对象里面的UndoableEditListener。
然后在这个自定义的UndoableEditListener的undoableEditHappened函数中,获取UndoableEdit对象并将这个对象传递给UndoManager,再刷新 undo,redo 按钮或菜单。

undo/redo的按钮或菜单中需要处理的操作就是undoManager.undo()或者undoManager.redo()然后更新按钮或菜单信息就行了。

Comments