使用备忘录模式实现Undo和Redo

备忘录模式有三个角色。
1.发起人(Originator)角色:负责创建一个备忘录,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。实现其他业务功能。
2.备忘录(Memento)角色:负责存储发起人的内部状态。
3.管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

网站的建设创新互联专注网站定制,经验丰富,不做模板,主营网站定制开发.小程序定制开发,H5页面制作!给你焕然一新的设计体验!已为成都户外休闲椅等企业提供专业服务。

/**
 * 发起人角色
 *
 */
public class UnRedoOriginator {
    private String state;

    public UnRedoOriginator() {
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

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

    public void restoreMemento(Memento m) {
        if (m != null) {
            this.setState(m.getState());
        } else {
            System.out.println("没有状态可恢复");
        }
    }
}
/**
 * 备忘录
 *
 */
public class Memento {
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}
/**
 * 可undo和redo的备忘录管理者
 *
 */
public class UnRedoCaretaker {
    /* 备忘列表 */
    private List<Memento> mementoList;
    /* 备忘列表容量,备忘列表容量 = 最大后退次数 + 1 */
    private int capacity = 3;
    /* 后退索引 */
    private int undoIndex = -2;
    /* 前进索引 */
    private int redoIndex = 0;

    public UnRedoCaretaker() {
        this.mementoList = new LinkedList<>();
    }

    public UnRedoCaretaker(int capacity) {
        this();
        this.capacity = capacity;
    }

    /**
     * 添加备忘
     * 
     * @param memento
     */
    public void addMemento(Memento memento) {
        // 添加备忘前,移除当前状态之后的备忘
        for (int i = this.mementoList.size() - 1; i > this.undoIndex + 1; i--) {
            this.mementoList.remove(i);
        }

        if (this.mementoList.size() >= this.capacity) {
            this.mementoList.remove(0);
        }
        this.mementoList.add(memento);

        this.undoIndex = this.mementoList.size() - 2;
        this.redoIndex = this.mementoList.size();
    }

    /**
     * 后退操作
     * 
     * @return
     */
    public Memento undo() {
        Memento result = null;

        if (this.undoIndex >= 0 && this.undoIndex < this.mementoList.size() - 1) {
            result = this.mementoList.get(this.undoIndex);

            this.undoIndex--;
            this.redoIndex--;
        }

        return result;
    }

    /**
     * 前进操作
     * 
     * @return
     */
    public Memento redo() {
        Memento result = null;
        if (this.redoIndex > 0 && this.redoIndex < this.mementoList.size()) {
            result = this.mementoList.get(this.redoIndex);

            this.redoIndex++;
            this.undoIndex++;
        }

        return result;
    }
}

把发起人角色与备忘录管理者角色聚合在一起,修改发起人角色类。

/**
 * 发起人角色
 *
 */
public class UnRedoOriginator {
    private String state;
    private UnRedoCaretaker caretaker;

    public UnRedoOriginator() {
        this.caretaker = new UnRedoCaretaker(3);
    }

    private void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    private Memento createMemento() {
        return new Memento(state);
    }

    private void restoreMemento(Memento m) {
        if (m != null) {
            this.setState(m.getState());
        } else {
            System.out.println("没有状态可恢复");
        }
    }

    public void setAndStoreState(String state) {
        this.setState(state);
        caretaker.addMemento(this.createMemento());
    }

    public void undo() {
        this.restoreMemento(caretaker.undo());
    }

    public void redo() {
        this.restoreMemento(caretaker.redo());
    }
}

测试。

/**
 * 测试 undo和redo
 * 
 */
public class TestUnRedo {

    public static void main(String[] args) {
        UnRedoOriginator or = new UnRedoOriginator();

        /* 未设置状态前进后退 */
        or.undo();
        or.redo();

        /* 连续添加操作 */
        System.out.println();
        int num = 1;
        operation(or, num++);
        operation(or, num++);
        operation(or, num++);
        operation(or, num++);

        /* 后退次数超过可后退次数 */
        back(or);
        back(or);
        back(or);

        /* 后退时添加新操作,然后再后退 */
        System.out.println();
        operation(or, num++);
        back(or);
        forward(or);
        forward(or);// 前进次数超过可前进次数

        /* 后退时添加新操作,然后redo */
        System.out.println();
        back(or);
        operation(or, num++);
        forward(or);
    }

    private static void operation(UnRedoOriginator or, int name) {
        System.out.println("*******操作*******");
        or.setAndStoreState("操作" + name);
        System.out.println("当前状态:" + or.getState());
    }

    private static void back(UnRedoOriginator or) {
        System.out.println("-------后退-------");
        or.undo();
        System.out.println("当前状态:" + or.getState());
    }

    private static void forward(UnRedoOriginator or) {
        System.out.println("=======前进=======");
        or.redo();
        System.out.println("当前状态:" + or.getState());
    }

}

运行结果如下。

没有状态可恢复
没有状态可恢复

*******操作*******
当前状态:操作1
*******操作*******
当前状态:操作2
*******操作*******
当前状态:操作3
*******操作*******
当前状态:操作4
-------后退-------
当前状态:操作3
-------后退-------
当前状态:操作2
-------后退-------
没有状态可恢复
当前状态:操作2

*******操作*******
当前状态:操作5
-------后退-------
当前状态:操作2
=======前进=======
当前状态:操作5
=======前进=======
没有状态可恢复
当前状态:操作5

-------后退-------
当前状态:操作2
*******操作*******
当前状态:操作6
=======前进=======
没有状态可恢复
当前状态:操作6

分享名称:使用备忘录模式实现Undo和Redo
文章位置:https://www.cdcxhl.com/article18/gjppdp.html

成都网站建设公司_创新互联,为您提供品牌网站制作网站改版品牌网站建设用户体验移动网站建设响应式网站

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

网站托管运营