备忘录模式(行为型)

来源:互联网 发布:计算机程序员工资待遇 编辑:程序博客网 时间:2024/05/21 09:19

备忘录模式(Memento Pattern),又称为快照(snapshot)模式,或Token模式;
备忘录模式定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存该状态.这样,以后就可以将该对象恢复到原先的状态.
如:联机事务处理时,需要对原子操作前的状态备份一下,以便原子操作失败时能回滚,因此需要用到备忘录模式;


实例:系统需要对一个文档对象的不同状态进行备份,以便后期可以回退,如何设计?

因为文档对象存在很多不需要备份的属性,如文档大小,文档名称等很多信息,所以我们有必要新建一个类(快照类)专门表示一次备份的信息.然后使用另外一个类专门管理所有的快照对象.如图(document对象提供产生快照对象的方法,因此是依赖关系,一个版本系统中保存多个快照对象):

这里写图片描述

Document文档类:

package com.shusheng.pattern.memento;//重要文档public class Document {    String content;// 需要备份的状态    String otherContent;// 不需要备份的状态    // 保存为一个备份对象    public Backup save() {        System.out.println("保存备份");        return new Backup(content);    }    // 恢复为某个状态    public void resume(Backup backup) {        System.out.println("恢复备份");        content = backup.content;    }    @Override    public String toString() {        return "content : " + content + ", otherContent: " + otherContent;    }}

Backup快照类:

package com.shusheng.pattern.memento;//备份对象public class Backup {    String content;//备份内容    int version;//版本    public Backup(String content) {        this.content = content;    }}

VersionControlSystem版本控制系统,专门管理快照对象:

package com.shusheng.pattern.memento;import java.util.LinkedList;//版本控制系统public class VersionControlSystem {    LinkedList<Backup> backups =  new LinkedList<>();//使用链表管理快照对象    int nextVersion;    //添加快照对象    public void add(Backup backup){        backup.version = ++nextVersion;        backups.add(backup);    }    //获取特定版本快照    public Backup get(int version) {        for(Backup backup : backups)            if(backup.version == version)                 return backup;        return null;    }    //取得最后一个快照对象    public Backup getLastVersion() {        return backups.getLast();    }}

Test测试类:

package com.shusheng.pattern.memento;public class Test {    public static void main(String[] args) {        VersionControlSystem vcs = new VersionControlSystem();        Document document = new Document();        document.content = "content1";        document.otherContent = "otherContent1";        System.out.println(document);         vcs.add(document.save());//保存一个快照对象,document.save()生成快照对象        document.content="content2";        document.otherContent = "otherContent2";        System.out.println(document);        vcs.add(document.save());//保存一个快照对象        document.content = "content3";        document.otherContent = "otherContent3";        System.out.println(document);        vcs.add(document.save());//保存一个快照对象        System.out.println("版本控制系统的版本数量:"+vcs.backups.size());        System.out.println("------------------------");        document.resume(vcs.get(1));//回退到版本1        System.out.println(document);        document.resume(vcs.getLastVersion());//回退到最新版本        System.out.println(document);    }}

结果分析:
首先连续向版本控制系统添加了三个快照对象(otherContent信息是不在备份范围内的).
此时版本控制系统的快照数量为3;
恢复备份时因为otherContent没在备份范围内,所以信息不回退,而content的信息回退到了第一个版本.
然后又让文档对象回归到最新版(第三版);
这里写图片描述


备忘录模式使用场景:
1. 需要保存和恢复数据的相关状态场景.
2. 提供一个可回滚的操作.
3. 需要监控副本的场景.
4. 数据库链接的事务管理(使用的就是备忘录模式)


备忘录模式的注意事项 :
1. 备忘录的生命周期:备忘录对象创建出来就是再最近的代码中使用,要主动管理它的生命周期,建立就要使用,不使用就要立刻删除其引用,等待垃圾回收器对它的回收处理,避免占用内存;
2. 备忘录的性能: 不要在频繁建立备份的场景中使用备忘录模式,例如:for循环.一是控制不了备忘录建立的数量,二是大对象的建立时要消耗资源的,需要考虑系统的性能.

1 0