当前位置: 首页 > news >正文

《java与模式》学习系列——备忘录模式

 

一、 备忘录(Memento)模式结构

备忘录对象是一个用来存储另外一个对象内部状态的快照(snapshot)的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉住,并外部化,存储起来,从而可以在将来适合的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。

其结构图如下:

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

备忘录角色:

(1)       将发起人对象的内部状态存储起来,备忘录可以根据发起人对象的判断来决定存储多少发起人对象的内部状态。

(2)       备忘录可以保护其内容不被发起人对象之外的任何对象所读取。

备忘录有两个等效的接口:

窄接口:负责人(Caretaker)对象和其他除发起人对象之外的任何对象看到的是备忘录的窄接口(narrow interface),这个窄接口只允许它把备忘录对象传给其他对象。

宽接口:与负责人对象看到的窄接口相反的是,发起人对象可以看到一个宽接口(wide interface),这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。

发起人角色:

(1)       创建一个含有当前的内部状态的备忘录对象。(2)使用备忘录对象存储其内部状态。

负责人角色:

(1)       负责保存备忘录对象。(2)不检查备忘录对象的内容。

二、 实现

双重接口,就是同一个接口对某一个对象提供宽接口,而对另一些对象提供窄接口。根据编程语言的性能,双重接口的实现方式有所不同。在C++中可以通过接口设置成私有同时将提供宽接口的对象设置为该接口的友元类即可。在java中则要通过把该接口的实现作为提供宽接口的对象的内部类来达到。

可以将Memento设成Originator类的内部类,从而将Memento对象封装在Originator里面;在外部提供一个标识接口MementorIFMemento类实现MementorIF接口)给Caretaker以及其他对象。这样,Originator类看到的是Mementor的所有接口,而Caretaker以及其他对象看到的仅仅是标识接口MementoIF所暴露出来的接口。

类图如下:

代码如下:

 

三、 备忘录模式在Java中的应用

J2EE框架中备忘录模式的应用

Java引擎提供Session对象,可以弥补HTTP协议的无状态缺点,存储用户的状态。当一个新的网络用户调用一张JSP网页或者Servlet时,Servlet引擎会创建一个对应于这个用户的Session对象,具体的技术细节可能是向客户端浏览器发送一个含有Session IDCookie,或者使用URL改写技术将Session ID 包括在URL中等。在一段有效时间里,同一个浏览器可以反复访问服务器,而Servlet引擎便可以使用这个Session ID来判断来访者应当与哪一个Session对象对应。SessionCookie的使用都是备忘录模式,如下图所示:

四、 备忘录模式的优缺点

优点:

1、  有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取。这时,使用备忘录可以把复杂的发起人内部信息对其他的对象屏弊起来,从而可以恰当地保持封装的边界。

2、  本模式简化了发起人类,发起人不再需要管理和保存其内部状态的一个个版本,客户端可以自行管理它们所需要的这些状态的版本。

3、  当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。

缺点:

1、  如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。

2、  当负责人角色将一个备忘录存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否会昂贵。

 

相关文章:

  • 向量加减法运算及其几何意义
  • 关于 Java 中 finally 语句块的深度辨析
  • Linux 基础(一)
  • Windows 7 应用程序exe图标丢失的修复
  • 算法导论学习笔记——堆排序
  • 让Docker容器使用静态独立的外部IP(便于集群组建)
  • 算法导论学习笔记——插入排序
  • 本地Git仓库与Github远程仓库同步
  • 算法导论学习笔记——合并排序
  • 算法导论学习笔记——最大优先级队列
  • Data.xml文件找不到的解决
  • 算法导论学习笔记——快速排序算法
  • instancetype
  • CentOS下SVN使用
  • java虚拟机学习笔记——java安全模型
  • Google 是如何开发 Web 框架的
  • 「面试题」如何实现一个圣杯布局?
  • Django 博客开发教程 8 - 博客文章详情页
  • HomeBrew常规使用教程
  • Java精华积累:初学者都应该搞懂的问题
  • Node + FFmpeg 实现Canvas动画导出视频
  • Swift 中的尾递归和蹦床
  • underscore源码剖析之整体架构
  • 从重复到重用
  • 仿天猫超市收藏抛物线动画工具库
  • 将 Measurements 和 Units 应用到物理学
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 如何胜任知名企业的商业数据分析师?
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 《天龙八部3D》Unity技术方案揭秘
  • Hibernate主键生成策略及选择
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • ​2021半年盘点,不想你错过的重磅新书
  • #android不同版本废弃api,新api。
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • (Java数据结构)ArrayList
  • (MATLAB)第五章-矩阵运算
  • (二)c52学习之旅-简单了解单片机
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (九十四)函数和二维数组
  • (六)vue-router+UI组件库
  • (一) springboot详细介绍
  • (转)Linq学习笔记
  • .cfg\.dat\.mak(持续补充)
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .NET 使用 XPath 来读写 XML 文件
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded
  • .NetCore项目nginx发布
  • /proc/vmstat 详解
  • @data注解_一枚 架构师 也不会用的Lombok注解,相见恨晚
  • @GetMapping和@RequestMapping的区别
  • [2010-8-30]
  • [20161214]如何确定dbid.txt
  • [3D游戏开发实践] Cocos Cyberpunk 源码解读-高中低端机性能适配策略