原文地址:折腾Java设计模式之备忘录模式

备忘录模式

Without violating encapsulation, capture and externalize an object's internal state allowing the object to be restored to this state later.

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃。通过一个备忘录类专门存储对象状态。客户不与备忘录类耦合,与备忘录管理类耦合。

备忘录模式UML

UML类图

Caretaker类是指用于保存(createMemento())和还原(restore(memento))发起方内部状态的Originator类。

发起方类实现

(1)createMemento(),通过创建和返回存储发起方当前内部状态的memento对象

(2)通过从传入的memento对象还原状态来还原(memento)。

UML时序图

(1)保存发起人的内部状态:Caretaker对Originator调用createMemento(),创建memento对象,保存其当前内部状态(setState()),并将memento返回给Caretaker。

(2)恢复发起人的内部状态:Caretaker对Originator调用restore(memento),并指定存储应恢复状态的memento对象。发起者从memento获取状态(getState())以设置其自己的状态。

备忘录模式角色结构

(1) 备忘录(Memento)角色:备忘录角色存储“备忘发起角色”的内部状态。“备忘发起角色”根据需要决定备忘录角色存储“备忘发起角色”的哪些内部状态。为了防止“备忘发起角色”以外的其他对象访问备忘录。备忘录实际上有两个接口,“备忘录管理者角色”只能看到备忘录提供的窄接口——对于备忘录角色中存放的属性是不可见的。“备忘发起角色”则能够看到一个宽接口——能够得到自己放入备忘录角色中属性。

(2) 备忘发起(Originator)角色:“备忘发起角色”创建一个备忘录,用以记录当前时刻它的内部状态。在需要时使用备忘录恢复内部状态。

(3) 备忘录管理者(Caretaker)角色:负责保存好备忘录。不能对备忘录的内容进行操作或检查。

干货示例

源码地址

public class Caretaker {

​    public static void main(String[] args) {
​ List<Memento> savedStates = new ArrayList();
​ Originator originator = new Originator();
​ originator.set("State1");
​ originator.set("State2");
​ savedStates.add(originator.saveToMemento()); ​ originator.set("State3");
​ savedStates.add(originator.saveToMemento()); ​ originator.set("State4");
​ originator.restoreFromMemento(savedStates.get(1));
​ }
} @Slf4j
public class Originator { ​ private String state; ​ //状态更改
​ public void set(String state) {
​ this.state = state;
​ log.info("Originator: Setting state to {}", state);
​ } ​ //将状态保存到备忘录里
​ public Memento saveToMemento() {
​ log.info("Originator: Saving to Memento.");
​ return new Memento(this.state);
​ } ​ //从备忘录里取出状态并回滚
​ public void restoreFromMemento(Memento memento) {
​ this.state = memento.getState();
​ log.info("Originator: State after restoring from Memento: {}", state);
​ }
} @Data
@AllArgsConstructor
public class Memento { ​ //状态维护
​ private String state; }

示例结果

从上述代码中看的出,随着状态变更,用List维护发起者的状态列表,从备忘录中取出状态以便回退状态。

java中的使用

生成对象状态的一个快照,以便对象可以恢复原始状态而不用暴露自身的内容。Date对象通过自身内部的一个long值来实现备忘录模式。

java.util.Date

java.io.Serializable

总结

优点

1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。 2、实现了信息的封装,使得用户不需要关心状态的保存细节。

缺点

消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

使用场景

1、需要保存/恢复数据的相关状态场景。 2、提供一个可回滚的操作。

注意事项

1、为了符合迪米特原则,还要增加一个管理备忘录的类。 2、为了节约内存,可使用原型模式+备忘录模式。

参考

备忘录模式|菜鸟教程

Memento pattern

细数JDK里的设计模式

欢迎关注

折腾Java设计模式之备忘录模式的更多相关文章

  1. 折腾Java设计模式之建造者模式

    博文原址:折腾Java设计模式之建造者模式 建造者模式 Separate the construction of a complex object from its representation, a ...

  2. 折腾Java设计模式之状态模式

    原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...

  3. 折腾Java设计模式之模板方法模式

    博客原文地址:折腾Java设计模式之模板方法模式 模板方法模式 Define the skeleton of an algorithm in an operation, deferring some ...

  4. 折腾Java设计模式之访问者模式

    博客原文地址:折腾Java设计模式之访问者模式 访问者模式 Represent an operation to be performed on the elements of an object st ...

  5. 折腾Java设计模式之命令模式

    博客原文地址 折腾Java设计模式之命令模式 命令模式 wiki上的描述 Encapsulate a request as an object, thereby allowing for the pa ...

  6. java设计模式之备忘录模式

    备忘录模式 备忘录模式是一种软件设计模式:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态.一听到备忘录这个字的时候想起了小小时打的游 ...

  7. 折腾Java设计模式之迭代器模式

    迭代器模式 Provide a way to access the elements of an aggregate object sequentially without exposing its ...

  8. java设计模式9.备忘录模式、访问者模式、调停者模式

    备忘录模式 备忘录模式又叫快照模式,备忘录对象是一个用来存储另外一个对象内部状态快照的对象.备忘录的用意是在不破坏封装的条件下,将一个对象的状态捕捉,并外部化存储起来,从而可以在将来合适的时候把这个对 ...

  9. Java设计模式应用——备忘录模式

    备忘录模式主要用于存档.游戏中我们打boss前总会存档,如果打boss失败,则读取存档,重新挑战boss. 可以看出来,备忘录模式一般包括如下数据结构 1. 存档文件:用于恢复备份场景的必要数据: 2 ...

随机推荐

  1. 深度学习之Batch Normalization

    在机器学习领域中,有一个重要的假设:独立同分布假设,也就是假设训练数据和测试数据是满足相同分布的,否则在训练集上学习到的模型在测试集上的表现会比较差.而在深层神经网络的训练中,当中间神经层的前一层参数 ...

  2. Jmeter利用正则表达式提取器提取登录cookie供下一步使用

    最近在学Jmeter,遇到需要登录之后才能进行下一步操作的场景,网上查了各位大神的资料,东拼西凑总算是做好满足需求了,写一下经过和步骤吧. 一.正常调用 按正常流程添加线程组.HTTP请求(登录和添加 ...

  3. 学习 JavaScript (四)核心概念:操作符

    JavaScript 的核心概念主要由语法.变量.数据类型.操作符.语句.函数组成,前面三个上一篇文章已经讲解完了.后面三个内容超级多,这篇文章主要讲解的是操作符. 操作符 什么叫做操作符? 这是一种 ...

  4. 一文快速了解MaxCompute

    很多刚初次接触MaxCompute的用户,面对繁多的产品文档内容以及社区文章,往往很难快速.全面了解MaxCompute产品全貌.同时,很多拥有大数据开发经验的开发者,也希望能够结合自身的背景知识,将 ...

  5. MobileForm控件的使用方式-用.NET(C#)开发APP的学习日志

    今天继续Smobiler开发APP的学习日志,这次是做一个title.toolbar.侧边栏三种效果 样式一 一.          Toolbar 1.       目标样式 我们要实现上图中的效果 ...

  6. vue之$root,$parent

    $root vue状态管理使用vuex,如果项目不大,逻辑不多,name我们没必要用vuex给项目增加难度,只需要用$root设置vue实例的data就行了,如下 main.js new Vue({ ...

  7. Angular(02)-- Angular-CLI命令

    声明 本系列文章内容梳理自以下来源: Angular 官方中文版教程 官方的教程,其实已经很详细且易懂,这里再次梳理的目的在于复习和巩固相关知识点,刚开始接触学习 Angular 的还是建议以官网为主 ...

  8. AndroidStduio3.0 使用gradle将module打包jar文件

    AndroidStduio3.0使用gradle将module打包jar文件,首先需要安装gradle. 打开控制台输入      open -e .bash_profile     命令,就可以打开 ...

  9. 4. [mmc subsystem] mmc core(第四章)——host模块说明

    零.说明 对应代码drivers/mmc/core/host.c,drivers/mmc/core/host.h. 为底层host controller driver实现mmc host的申请以及注册 ...

  10. C++基础——运算符重载友元函数示例

    一.前言 其实本人学习C++的目的,只是为了体会OOP设计思想,并为利用System Verilog验证复杂设计做准备.如果想要真正做点软件方面项目级的东西,还需要掌握其他高级语言和库.框架等知识.因 ...