备忘录模式实现撤销(Undo)和重做(Redo)功能

备忘录模式实现撤销和重做功能

    • 问题
    • 结构类图
    • 程序代码

问题

某文字编辑软件须提供撤销(Undo)和重做/恢复(Redo)功能,并且该软件可支持文档对象的多步撤销和重做。开发人员决定采用备忘录模式来实现该功能,在实现过程中引入栈(Stack)作为数据结构。在实现时,可以将备忘录对象保存在两个栈中,一个栈包含用于实现撤销操作的状态对象,另一个栈包含用于实现重做操作的状态对象。在实现撤销操作时,会弹出撤销栈栈顶对象以获取前一个状态并将其设置给应用程序;同样,在实现重做操作时,会弹出重做栈栈顶对象以获取下一个状态并将其设置给应用程序。

结构类图

备忘录模式实现撤销(Undo)和重做(Redo)功能_第1张图片

程序代码

//备忘录类
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();
    }
}

你可能感兴趣的:(设计模式,java,设计模式,数据库)