专栏首页dylanliu设计模式之备忘录模式

设计模式之备忘录模式

定义

备忘录模式(Momento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。又叫快照模式。

备忘录模式是一个比较简单的模式,用于备份对象状态。通常可以与命令模式等一起使用。

角色

备忘录模式有三个角色:备忘录(Memento)角色,发起人(Originator)角色,负责人(Caretaker)角色。

从类图上可以看出,发起人和备忘录角色都有 state 属性,其实可以把备忘录角色当作发起人角色的属性容器,发起人决定要备份哪些状态,并将状态放到备忘录中,备忘录存储这些状态,并且可以被保存起来,在需要的时候提供给发起人用于恢复到以前。

模式说明

我们结合命令模式来说明备忘录模式,依然使用浏览器的返回场景来说明。用户在浏览器中点击某个超链接跳到另一个页面,点击返回回到上一个链接页面,我们将点击抽象成命令,将返回抽象成恢复状态,浏览器就是我们的发起人角色。

/**
  * 在浏览器中是URL跳转
  */
public interface Command<T> {
    void execute(T param);
    void back();
}

@Data
public class Memento {
    private String url;
}
// 浏览器窗口
public class Window {
    private String url;
    
    public Memento createMemento() {
        Memento m = new Memento();
        m.setUrl(this.url);
        return m;
    }
    
    public void restoreMemento(Memento m) {
        rendUrlAndShow(m.getUrl());
    }
    
    public void rendUrlAndShow(String url) {
        this.url = url;
        System.out.println(url);
    }
}
public class UrlCommand implements Command<String> {
    private Window window;
    private Memento m;

    public void execute(String url) {
        this.m = window.createMemento();
        window.rendUrlAndShow(url);
    }
    
    public void back() {
        // 将原窗口再设置回去
        window.restoreMemento(m);
    }
}

public class User {
    public static void main(String[] args) {
        // 在浏览器里用户点击 a.com
        String url = "www.a.com";
        Command<String> commandA = new UrlCommand();
        commandA.execute(url);
        
        // 用户点击返回
        stack.pop().back();
    }
}

在这里 UrlCommand 既是 命令模式中的Command 角色也是备忘录模式中的 负责人角色。

模式变种

  1. 由于备忘录角色只是一个属性容器,用于保存需要的属性,因此发起人自己就可以充当备忘录角色,这时可以使原型模式来创建当前对象的克隆,然后保存这个副本即可
  2. 备忘录保存的是发起对象的属性,这些属性可以直接保存到 key-value 的 map 中,无需单独创建一个类
  3. 备忘录模式只是描述单一备份的情况,在有多个备份的情况下可以配合 Stack 等数据结构使用,例如浏览器支持多次返回,例子如下:
public class User {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        // 在浏览器里用户点击 a.com
        String url = "www.a.com";
        Command<String> commandA = new UrlCommand();
        commandA.execute(url);
        stack.push(commandA);
        // 用户点击b.com
        url = "www.b.com"
        Command<String> commandB = new UrlCommand();
        commandB.execute(url);
        stack.push(commandB);
        
        // 用户点击返回
        stack.pop().back();
        // 用户又点击一次返回
        stack.pop().back();
    }
}

优点

  • 在不破坏封装的前提下保存一个对象的状态
  • 与其他模式共同使用,可以方便实现一些功能,如命令模式的 undo
  • 备忘录模式是实现检查点(check point)的一种方法

缺点

  • 在备份对象过多时,会占用很多内存,此时需要与外部存储交互

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring Qualifier的使用

    spring 的 qualifier 平常使用一般直接是使用id 来限定,不过spring给我们提供了更强大的功能。

    Dylan Liu
  • curl (3) Illegal characters found in URL

    在windows 中编辑的文件上传到 Linux 后,使用 curl 等工具调用时会报一个curl: (3) Illegal characters found ...

    Dylan Liu
  • 设计模式之简单工厂模式

    简单工厂模式 Simple Factory Pattern 也叫静态工厂方法模式 Static Factory Method Pattern,隶属于设计模式中的...

    Dylan Liu
  • Android 二次封装网络加载框架

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/de...

    用户2965908
  • Java设计模式精讲(一):责任链模式

    这篇分享作为一个系列分享的第一篇,主要和大家一起学习一下java设计模式方面的基础,我们现在的安卓开发主要还是基于java语言,所以掌握java...

    open
  • [可视化]一张图看懂Python3

    大数据文摘
  • Java-正则表达式

    DataScience
  • Builder模式

    (1)相同的方法,不同的执行顺序,产生不同的事件结果时。 (2)多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时。 (3)产品类...

    提莫队长
  • 微信小程序请求server时遇到的2个问题

    简介 微信小程序与服务器的沟通逻辑并不复杂,流程: ? 前3步做好以后,我在最后一步遇到了2个问题,花费了很多时间,总结出来供大家在开发小程序时参考 问题1:...

    dys
  • 计算广告系列(三)-通过单品拍卖的例子通俗理解机制设计

    计算广告与机制设计密切相关,一个最为常见的例子就是广告的计费,比如采用一价计费还是二价计费。那么本文咱们先来简单了解一下机制设计的内容。

    石晓文

扫码关注云+社区

领取腾讯云代金券