设计模式(二十一)备忘录模式

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/niunai112/article/details/79990158

版权声明:转载必须注明本文转自晓_晨的博客:http://blog.csdn.net/niunai112

目录

导航

设计模式之六大设计原则
设计模式(一)单例模式
设计模式(二)工厂模式
设计模式(三)策略模式
设计模式(四)适配器模式
设计模式(五)享元模式
设计模式(六)建造者模式
设计模式(七)原型模式
设计模式(八)桥接模式
设计模式(九)外观模式
设计模式(十)组合模式
设计模式(十一)装饰器模式
设计模式(十二)代理模式
设计模式(十三)迭代器模式
设计模式(十四)观察者模式
设计模式(十五)中介者模式
设计模式(十六)命令模式
设计模式(十七)状态模式
设计模式(十八)访问者模式
设计模式(十九)责任链模式
设计模式(二十)解释器模式
设计模式(二十一)备忘录模式
设计模式(二十二)模板模式
设计模式总结篇(为什么要学习设计模式,学习设计模式的好处)

前言

备忘录模式(Memento Pattern):保存一个对象的某个状态,以便在适当的时候恢复对象。
备忘录角色(Memento):保存需要保存的所有状态,将其抽象成一个备忘录角色。
备忘发起角色(Originator):需要被备忘录记录状态并保存的角色,可以创建一个备忘录,用以记录当前时刻它的内部状态,可以使用备忘录恢复内部状态。
备忘录管理者角色(Caretaker):负责管理备忘录。不能对备忘录的内容进行操作或检查。只有保存和返回备忘录角色的功能。

例子

LZ以一部动漫为例子,LZ认为这部动漫能很好的体现这个模式,那就是《从零开始异世界》,相信很多人应该看过,若没有看过的,可以以游戏来替换。
里面的主角486,一开始的时候,总是不停的死亡,然后从某一时刻复活,然后继续。这个过程用备忘录模式来实现,就是
白箱实现,顾名思义,我们的Memento对象是完全对使用者开放的,使用者能直接看到Memento,以及直接对Memento 进行操作。

/***
 *
 *@Author ChenjunWang
 *@Description:备忘录模板(要返回的记录以这个格式保存)
 *@Date: Created in 10:57 2018/4/18
 *@Modified By:
 *
 */
public class Memento {
    private int time;
    public Memento(int time) {
    }

    public int getTime() {
        return time;
    }

    public void setTime(int time) {
        this.time = time;
    }
}

/***
 *
 *@Author ChenjunWang
 *@Description:备忘录发起者,也是需要被备忘的对象
 *@Date: Created in 10:57 2018/4/18
 *@Modified By:
 *
 */
public class Originator {
    private int time = 0;//刚进入的时候,486的时间节点是0


    public Memento creatMementoObject() {
        return new Memento(time);
    }


    public void restoreMemento(Memento memento) {
        this.time = memento.getTime();

    }

    public int getTime() {
        return time;
    }

    public void setTime(int time) {
        this.time = time;
    }
}

/***
 *
 *@Author ChenjunWang
 *@Description:看门人(负责备忘录的管理)
 *@Date: Created in 10:58 2018/4/18
 *@Modified By:
 *
 */
public class Caretaker {

    private Memento memento;

    //返回已保存的备忘录(用于恢复记录)
    public Memento retrieveMemento(){
        return this.memento;
    }


    //保存备忘录记录
    public void saveMemento(Memento memento) {
        this.memento = memento;
    }



}

/***
 *
 *@Author ChenjunWang
 *@Description:
 *@Date: Created in 11:26 2018/4/18
 *@Modified By:
 *
 */
public class Test {
    public static void main(String[] args) {

        Originator u486 = new Originator();
        Caretaker admin = new Caretaker();
        System.out.println("------------------486 来到了异世界----------------------");
        admin.saveMemento(u486.creatMementoObject());
        u486.setTime(100);
        System.out.println("------------------486 death----------------------");
        u486.restoreMemento(admin.retrieveMemento());
        System.out.println("-------------------从零开始-----------------------");
        System.out.println("486的时间变为:" + u486.getTime());

    }
}

运行结果如下
-----------------------------------------------------------------
------------------486 来到了异世界----------------------
------------------486 death----------------------
-------------------从零开始-----------------------
486的时间变为:0

黑箱实现,只需要把Memento替换成IMemento接口,把Originator替换即可。



/***
 *
 *@Author ChenjunWang
 *@Description:备忘录模板(要返回的记录以这个格式保存)
 *@Date: Created in 10:57 2018/4/18
 *@Modified By:
 *
 */
public interface IMemento {

}

/***
 *
 *@Author ChenjunWang
 *@Description:
 *@Date: Created in 10:57 2018/4/18
 *@Modified By:
 *
 */
public class Originator {
    private int time = 0;


    public IMemento creatMementoObject() {
        return new Memento(time);
    }


    public void restoreMemento(IMemento memento) {
        this.time = ((Memento)memento).getTime();

    }

    public int getTime() {
        return time;
    }

    public void setTime(int time) {
        this.time = time;
    }

    private  class Memento implements IMemento{
        private int time;
        public Memento(int time) {
        }

        public int getTime() {
            return time;
        }

        public void setTime(int time) {
            this.time = time;
        }
    }


}


/***
 *
 *@Author ChenjunWang
 *@Description:测试类
 *@Date: Created in 11:26 2018/4/18
 *@Modified By:
 *
 */
public class Test {
    public static void main(String[] args) {

        Originator u486 = new Originator();
        Caretaker admin = new Caretaker();
        System.out.println("------------------486 来到了异世界----------------------");
        admin.saveMemento(u486.creatMementoObject());
        u486.setTime(100);
        System.out.println("------------------486 death----------------------");
        u486.restoreMemento(admin.retrieveMemento());
        System.out.println("-------------------从零开始-----------------------");
        System.out.println("486的时间变为:" + u486.getTime());

    }
}
运行结果如下
---------------------------------------------------
------------------486 来到了异世界----------------------
------------------486 death----------------------
-------------------从零开始-----------------------
486的时间变为:0

在黑箱里,我们只传递IMemento,不需要知道里面的结构就是怎么样的, 因为Memento是内部类,被Originator隐藏在里面,解析也是通过Originator自己解析然后使用的,更加符合安全性,最小可见性这些要求。

以上两个代码都只是实线了单点存储,即只能保存一个状态,假如要保存多个状态,其实也很简单,LZ在这个点就不展开讲了,大家如果觉得有必要的话,可以在我的基础上进行拓展,基本就是用个数据结构来存储,比如List,或者Map,然后存和取的代码进行相应调整即可。

总结

优点

(1)提供了一种可以恢复状态的机制,可以使用户回到之前存储过的状态。

缺点

(1)需要消耗额外的空间来存放要保存状态信息,如果需要保存掉的类的成员信息很多,如果是多点记录保存,那用在存储状态所用的资源也是很巨大的。(实现了某种功能肯定是有付出的,当LZ觉得比起付出,备忘录模式的回报在关键时刻决定是非常非常有用的486靠这个保命,你说重不重要)

Git地址

本篇实例Github地址:https://github.com/stackisok/Design-Pattern/tree/master/src/memento

回到最上方


有什么不懂或者不对的地方,欢迎留言。
喜欢LZ文章的小伙伴们,可以关注一波,也可以留言,LZ会回你们的。
觉得写得不错的小伙伴,欢迎转载,但请附上原文地址,谢谢^_^!

展开阅读全文

没有更多推荐了,返回首页