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

【设计模式-4.7】行为型——备忘录模式

说明:本文介绍行为型设计模式之一的备忘录模式

定义

备忘录模式(Memento Pattern)又叫作快照模式(Snapshot Pattern)或令牌模式(Token Pattern)指在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态,属于行为型设计模式。

(引自《设计模式就该这样学》P348,发现作者很喜欢使用”XX模式又叫作XX模式“这样的表述,苦笑)

编辑器

假设开发一款编辑器软件,如下,有载入文档、追加内容、清空内容功能;

(文档类,Doc)

/*** 文档类*/
public class Doc {/*** 文档标题*/private String title;/*** 文档内容*/private StringBuffer body;public Doc(String title) {this.title = title;this.body = new StringBuffer();}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public StringBuffer getBody() {return body;}public void setBody(StringBuffer body) {this.body = body;}
}

(编辑器,Editor)

/*** 编辑器类*/
public class Editor {private Doc doc;/*** 载入文档*/public Editor(Doc doc) {System.out.println(">>>载入文档");this.doc = doc;show();}/*** 追加内容*/public void append(String content){System.out.println(">>>追加内容");doc.getBody().append(content);show();}/*** 清空内容*/public void clear() {System.out.println(">>>清空文档");doc.getBody().setLength(0);show();}/*** 保存内容*/public void save() {System.out.println(">>>保存中");// todoSystem.out.println(">>>保存成功");}/*** 展示内容*/public void show() {System.out.println(">>>展示内容");System.out.println("文档标题:" + doc.getTitle());System.out.println("文档内容:" + doc.getBody());}
}

(客户端使用,Client)

public class Client {public static void main(String[] args) {// 打开编辑器,开始写作Editor myDoc = new Editor(new Doc("《论程序员的自我修养》"));// 巴拉巴拉,写作中myDoc.append("\n第一章:程序员必备知识");myDoc.append("\n第二章:论艺术涵养对程序员编码的影响");// 看看,嗯,写得很好myDoc.show();// 保存myDoc.save();// 继续myDoc.append("\n第三章:论打游戏技术与程序员技术之间的关联");// 误操作。。。myDoc.clear();}
}

可见,如果误操作导致文档内容被清空,九分甚至十分的糟糕

在这里插入图片描述

针对以上功能,利用备忘录模式进行改造,如下:

(首先,创建一个历史记录对象,保存文档内容,History)

/*** 历史记录类*/
public class History {private StringBuffer body;public History(StringBuffer body) {this.body = body;}public StringBuffer getBody() {return body;}
}

(其次,文档对象中,增加保存历史记录,恢复历史记录的方法)

/*** 文档类*/
public class Doc {/*** 文档标题*/private String title;/*** 文档内容*/private StringBuffer body;public Doc(String title) {this.title = title;this.body = new StringBuffer();}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public StringBuffer getBody() {return body;}public void setBody(StringBuffer body) {this.body = body;}/*** 创建历史记录*/public History createHistory() {return new History(new StringBuffer(body));}/*** 恢复历史记录*/public void restoreHistory(History history) {body = history.getBody();}
}

注意创建历史记录方法里,使用了new StringBuffer(body),而不是直接传递body,这里涉及到深拷贝、浅拷贝的问题,大家可以试试看有什么区别。

(最后,改造编辑器类,增加撤销上一步操作的方法,并在每次修改操作后增加创建快照操作)

import java.util.List;/*** 编辑器类*/
public class Editor {/*** 文档对象*/private Doc doc;/*** 历史记录集合*/private List<History> historyList;/*** 历史记录版本号* 初始值为-1*/private int historyVersion = -1;/*** 载入文档*/public Editor(Doc doc) {System.out.println(">>>载入文档");this.doc = doc;historyList = new java.util.ArrayList<>();backup();show();}/*** 追加内容*/public void append(String content){System.out.println(">>>追加内容");doc.getBody().append(content);backup();show();}/*** 清空内容*/public void clear() {System.out.println(">>>清空文档");doc.getBody().setLength(0);backup();show();}/*** 保存内容*/public void save() {System.out.println(">>>保存中");// todoSystem.out.println(">>>保存成功");}/*** 展示内容*/public void show() {System.out.println(">>>展示内容");System.out.println("文档标题:" + doc.getTitle());System.out.println("文档内容:" + doc.getBody());}/*** 保存历史记录* 或者说创建快照*/private void backup() {historyList.add(doc.createHistory());historyVersion++;}/*** 撤回上一步*/public void undo() {System.out.println(">>>撤销操作");if (historyVersion == 0) {return;}historyVersion--;History history = historyList.get(historyVersion);doc.restoreHistory(history);show();}
}

(客户端使用,Client)

public class Client {public static void main(String[] args) {// 打开编辑器,开始写作Editor myDoc = new Editor(new Doc("《论程序员的自我修养》"));// 巴拉巴拉,写作中myDoc.append("\n第一章:程序员必备知识");myDoc.append("\n第二章:论艺术涵养对程序员编码的影响");// 看看,嗯,写得很好myDoc.show();// 保存myDoc.save();// 继续myDoc.append("\n第三章:论打游戏技术与程序员技术之间的关联");// 误操作。。。myDoc.clear();// 撤回上一步myDoc.undo();}
}

可见撤销操作成功恢复内容

在这里插入图片描述

多次撤销,可实现逐步回退操作

        // 撤回上一步myDoc.undo();myDoc.undo();myDoc.undo();myDoc.undo();

如下,非常nice。如果需要开发往后撤退的功能,也完全可以。

在这里插入图片描述

使用场景

在《设计模式就该这样学》(P365)这本书中,提到状态模式适用于以下场景:

(1)需要保存历史快照的场景。

(2)希望在对象之外保存状态,且除了自己,其他类对象无法访问状态保存的具体内容。

我觉得如果项目中,需要保存历史记录的场景,可以考虑使用备忘录模式进行改造。

总结

本文介绍了行为型设计模式中的状态模式,参考《设计模式就该这样学》、《秒懂设计模式》两书,编辑器场景是《秒懂设计模式》中的举例。

http://www.xdnf.cn/news/10746.html

相关文章:

  • 欢乐熊大话蓝牙知识14:用 STM32 或 EFR32 实现 BLE 通信模块:从0到蓝牙,你也能搞!
  • 机器人现可完全破解验证码:未来安全技术何去何从?
  • 【JAVA版】意象CRM客户关系管理系统+uniapp全开源
  • GoFrame框架深度解析:从gset模块看高效Go开发的实战之道
  • Java复习Day26
  • 2025年微信小程序开发:AR/VR与电商的最新案例
  • windows修改跃点数调整网络优先级
  • Leetcode - 周赛 452
  • 帝可得- 人员管理
  • vue+cesium示例:地形开挖(附源码下载)
  • 进程——环境变量及程序地址空间
  • vscode配置lua
  • React从基础入门到高级实战:React 高级主题 - React 微前端实践:构建可扩展的大型应用
  • Ubuntu 系统部署 MySQL 入门篇
  • 本地部署开源防病毒引擎 ClamAV 并实现外部访问(Windows 版本)
  • 研发型企业如何面对源代码保密问题
  • 不动产登记区块链系统(Vue3 + Go + Gin + Hyperledger Fabric)
  • 焊缝缺陷焊接缺陷识别分割数据集labelme格式5543张4类别
  • Neo4j 数据可视化与洞察获取:原理、技术与实践指南
  • 便捷高效能源服务触手可及,能耗监测系统赋能智能建筑与智慧城市
  • 12、企业应收账款(AR)全流程解析:从发票开具到回款完成
  • 【Web应用】若依框架:基础篇13 源码阅读-前端代码分析
  • MySQL 8 完整安装指南(Ubuntu 22.04)
  • 【论文解读】ReAct:从思考脱离行动, 到行动反馈思考
  • winrm登录失败,指定的凭据被服务器拒绝
  • Bash shell四则运算
  • 【Elasticsearch】search_after不支持随机到哪一页,只能用于上一页或下一页的场景
  • 涨薪技术|0到1学会性能测试第95课-全链路脚本开发实例
  • https(SSL)证书危机和可行的解决方案
  • 香橙派3B学习笔记6:基本的Bash脚本学习_UTF-8格式问题