问题
某文字编辑软件须提供撤销(Undo)和重做/恢复(Redo)功能,并且该软件可支持文档对象的多步撤销和重做。开发人员决定采用备忘录模式来实现该功能,在实现过程中引入栈(Stack)作为数据结构。在实现时,可以将备忘录对象保存在两个栈中,一个栈包含用于实现撤销操作的状态对象,另一个栈包含用于实现重做操作的状态对象。在实现撤销操作时,会弹出撤销栈栈顶对象以获取前一个状态并将其设置给应用程序;同样,在实现重做操作时,会弹出重做栈栈顶对象以获取下一个状态并将其设置给应用程序。
结构类图
程序代码
//备忘录类
public class Memento {
private String state;
public Memento(UnRedoOriginator unRedoOriginator) {
this.state=unRedoOriginator.getState();
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
// 负责undo和redo操作执行的类
public class UnRedoCaretaker {
// undo操作使用的备忘录列表
private List<Memento> undoList;
// redo操作使用的备忘录列表
private List<Memento> redoList;
public UnRedoCaretaker() {
undoList=new ArrayList<>();
redoList=new ArrayList<>();
}
public void addMemento(Memento memento){
// undoList添加新的备忘录之前,删除redo操作备忘录列表中的备忘录
for (int i=redoList.size()-1;i>=0;i--){
redoList.remove(i);
}
undoList.add(memento);
}
/*undoList中的最后一个memento代表当前状态*/
public Memento undo(){
Memento result=null;
if (undoList.size()>1){
/*获取undoList中的倒数第二个memento,才是需要返回的状态*/
result=undoList.get(undoList.size()-2);
/*将undoList中的表示当前状态的memento,存储至redoList中 */
redoList.add(undoList.get(undoList.size()-1));
/*将undoList中的表示当前状态的memento移除*/
undoList.remove(undoList.size()-1);
}else {
System.out.println("fail to undo operation!");
}
return result;
}
public Memento redo(){
Memento result=null;
if(redoList.size()>0){
result=redoList.get(redoList.size()-1);
undoList.add(result);
redoList.remove(redoList.size()-1);
}else {
System.out.println("fail to redo operation!");
}
return result;
}
}
// 发起人,负责创建和设置备忘录的状态
public class UnRedoOriginator {
private String state;
private UnRedoCaretaker unRedoCaretaker;
public UnRedoOriginator() {
unRedoCaretaker=new UnRedoCaretaker();
}
public Memento createMemento(){
return new Memento(this);
}
public void restoreMemento(Memento memento){
this.state=memento.getState();
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public void setAndStoreState(String state){
this.setState(state);
unRedoCaretaker.addMemento(this.createMemento());
}
public void undo(){
Memento memento=unRedoCaretaker.undo();
if (memento!=null){
System.out.println(memento.getState());
}
}
public void redo(){
Memento memento=unRedoCaretaker.redo();
if (memento!=null) {
System.out.println(memento.getState());
}
}
}
//测试类
public class Client {
public static void main(String[] args) {
UnRedoOriginator originator=new UnRedoOriginator();
System.out.println("执行的操作顺序:add sub mul div");
originator.setAndStoreState("add");
originator.setAndStoreState("sub");
originator.setAndStoreState("mul");
originator.setAndStoreState("div");
System.out.println("第一次undo操作:");
originator.undo();
System.out.println("第二次undo操作:");
originator.undo();
System.out.println("第一次redo操作:");
originator.redo();
System.out.println("第三次undo操作:");
originator.undo();
System.out.println("第四次undo操作:");
originator.undo();
System.out.println("第二次redo操作:");
originator.redo();
}
}