登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
社区
BBS
广播
Follow
园子
关于
博客
发1篇日志+1圆
记录
发1条记录+2圆币
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
VIP申请
网盘
联系我们
道具
勋章
任务
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
【备忘录设计模式详解】C/Java/JS/Go/Python/TS不同语言 ...
【备忘录设计模式详解】C/Java/JS/Go/Python/TS不同语言实现
[ 复制链接 ]
呵烘稿
2025-6-6 09:46:05
简介
备忘录模式(Memento Pattern)是一种结构型设计模式。这种模式就是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并放在外部存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。
备忘录模式的角色有三个:备忘录(Memento)角色、发起人(Originator)角色、负责人(Caretaker)角色
备忘录模式是由发起人(Originator)对象负责生成状态快照,其他对象不可修改状态。再将对象状态的副本存储在一个名为备忘录(Memento)的特殊对象中。除了创建备忘录的对象外,任何对象都不能访问备忘录的内容。其他对象必须使用指定接口与备忘录进行交互,它们可以获取快照的元数据(创建时间和操作名称等),但不能获取快照中原始对象的状态。
这种限制策略允许你将备忘录保存在通常被称为负责人(Caretakers)的对象历史中。由于负责人仅通过受限接口与备忘录互动,故其无法修改存储在备忘录内部的状态。同时,发起人拥有对备忘录所有成员的访问权限,从而能随时恢复其以前的某个状态。
作用
给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
实现了内部状态的封装,除了创建它的发起人之外,其他对象都不能够访问这些状态信息,也不需要关心状态的保存细节。
简化了发起人角色,发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由负责人进行管理,符合单一职责原则。
实现步骤
创建备忘录Memento,用来记录操作状态数据的实体类。
创建发起人角色Originator,状态的制造者,也是备忘录的生成者,负责将状态写入到一个新备忘录。
创建负责人角色Caretaker,用来保存和读取备忘录的历史记录,所有备忘录均可以保存在历史中,以便恢复。
客户调用方通过Originator来生成备忘录,再通过Caretaker读取和恢复备忘录历史记录。
UML
Java代码
具体备忘录
// Memento.java 备忘录(Memento)角色,负责存储发起人传入的状态
public class Memento {
private String state;
public Memento(String state) {
System.out.println(this.getClass().getName() + "::Memento() [state = " + state + "]");
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
复制代码
发起人
// Originator.java 发起人(Originator)负责生成状态快照,即利用一个新备忘录对象将自己的内部状态存储起来
public class Originator {
private String state;
// 每次创建一个新备忘录来保存状态
public Memento saveMemento() {
System.out.println(this.getClass().getName() + "::saveMemento() [state = " + state + "]");
return new Memento(state);
}
// 从备忘录中恢复状态
public void restoreMemento(Memento memento) {
this.state = memento.getState();
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
复制代码
负责人类
// Caretaker.java 负责人(Caretaker)角色,只负责保存备忘录记录,不能修改备忘录对象的内容
public class Caretaker {
// 备忘录可以是一个记录,也可以就是一个对象,根据业务场景设置
private List<Memento> mementoList = new ArrayList<Memento>();
public void add(Memento memento) {
System.out.println(this.getClass().getName() + "::add() [memento = " + memento.getClass().getName() + "]");
mementoList.add(memento);
}
public Memento get(int index) {
return mementoList.get(index);
}
public List<Memento> getMementoList() {
return this.mementoList;
}
}
复制代码
测试调用
/*
* 备忘录模式是在不暴露对象实现细节的情况下保存和恢复对象之前的状态。
* 先声明发起人Originator,再声明负责人Caretaker,发起人生成备忘录Memento
* 通过负责人则保存备忘录历史记录,读取备忘录由负责人来完成。
*/
Originator originator = new Originator();
Caretaker careTaker = new Caretaker();
// 发起人产生一个状态
originator.setState("state1");
// 覆盖了状态,那么前面的状态未保存
originator.setState("state2");
// 发起人生成备忘录,一般添加时直接保存即可
Memento memento = originator.saveMemento();
// 负责人保添加备忘录历史记录
careTaker.add(memento);
// 直接生成备忘录并添加到负责人的备忘录列表
originator.setState("state3");
careTaker.add(originator.saveMemento());
originator.setState("state4");
careTaker.add(originator.saveMemento());
System.out.println("发起人当前的状态: " + originator.getState());
// 发起人通过负责人那里取出状态
originator.restoreMemento(careTaker.get(0));
System.out.println("第一个保存的状态: " + originator.getState());
originator.restoreMemento(careTaker.get(1));
System.out.println("第二个保存的状态: " + originator.getState());
// 遍历全部备忘录
for (int i = 0; i < careTaker.getMementoList().size(); i++) {
// 外部一般不直接访问备忘录里面的状态,而是逐个恢复备忘录,再取出状态来
originator.restoreMemento(careTaker.get(i));
System.out.println("state: " + i + ")" + originator.getState());
}
复制代码
JavaScript代码
具体备忘录
// Memento.js 备忘录(Memento)角色,负责存储发起人传入的状态
// 备忘录(Memento)角色,负责存储发起人传入的状态
export class Memento {
constructor(state) {
console.log(this.constructor.name + '::Memento() [state = ' + state + ']')
this.state = state
}
getState() {
return this.state
}
setState(state) {
this.state = state
}
}
复制代码
发起人
// Originator.js 发起人(Originator)负责生成状态快照,即利用一个新备忘录对象将自己的内部状态存储起来
import { Memento } from './Memento.js'
export class Originator {
constructor() {
this.state = undefined
}
// 每次创建一个新备忘录来保存状态
saveMemento() {
console.log(
this.constructor.name + '::saveMemento() [state = ' + this.state + ']'
)
return new Memento(this.state)
}
// 从备忘录中恢复状态
restoreMemento(memento) {
this.state = memento.getState()
}
getState() {
return this.state
}
setState(state) {
this.state = state
}
}
复制代码
负责人类
// Caretaker.js 负责人(Caretaker)角色,只负责保存备忘录记录,不能修改备忘录对象的内容
export class Caretaker {
constructor() {
// 备忘录可以是一个记录,也可以就是一个对象,根据业务场景设置
this.mementoList = []
}
add(memento) {
console.log(
this.constructor.name +
'::add() [memento = ' +
memento.constructor.name +
']'
)
this.mementoList.push(memento)
}
get(index) {
return this.mementoList[index]
}
getMementoList() {
return this.mementoList
}
}
复制代码
测试调用
import { Originator } from '../src/Originator.js'
import { Caretaker } from '../src/Caretaker.js'
export function test() {
/*
* 备忘录模式是在不暴露对象实现细节的情况下保存和恢复对象之前的状态。
* 先声明发起人Originator,再声明负责人Caretaker,发起人生成备忘录Memento
* 通过负责人则保存备忘录历史记录,读取备忘录由负责人来完成。
*/
const originator = new Originator()
const careTaker = new Caretaker()
// 发起人产生一个状态
originator.setState('state1')
// 覆盖了状态,那么前面的状态未保存
originator.setState('state2')
// 发起人生成备忘录,一般添加时直接保存即可
const memento = originator.saveMemento()
// 负责人保添加备忘录历史记录
careTaker.add(memento)
// 直接生成备忘录并添加到负责人的备忘录列表
originator.setState('state3')
careTaker.add(originator.saveMemento())
originator.setState('state4')
careTaker.add(originator.saveMemento())
console.log('发起人当前的状态: ' + originator.getState())
// 发起人通过负责人那里取出状态
originator.restoreMemento(careTaker.get(0))
console.log('第一个保存的状态: ' + originator.getState())
originator.restoreMemento(careTaker.get(1))
console.log('第二个保存的状态: ' + originator.getState())
// 遍历全部备忘录
for (let i = 0; i < careTaker.getMementoList().length; i++) {
// 外部一般不直接访问备忘录里面的状态,而是逐个恢复备忘录,再取出状态来
originator.restoreMemento(careTaker.get(i))
console.log('state: ' + i + ')' + originator.getState())
}
}
// 执行测试
;(function () {
console.log('test start:')
test()
})()
复制代码
更多语言版本
不同语言实现设计模式:https://github.com/microwind/design-pattern
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
那些年搞不懂的高深术语——依赖倒置•控制反转•依赖注入•面向接口编程
如何优雅的使用RabbitMQ
分布式锁1 Java常用技术方案
浅谈我对DDD领域驱动设计的理解
游戏编程十年总结(下)
【前端性能】高性能滚动 scroll 及页面渲染优化
验证码对抗之路及现有验证机制介绍
从零开始入门 K8s | 手把手带你理解 etcd
NHibernate之旅(2):第一个NHibernate程序
中文写程序,何陋之有?
谈谈如何从本质上理解sql语句, 存储过程,ORM之间的联系和取舍。
公司的中场
模板模式
[一步一步MVC]第一回:使用ActionSelector控制Action的选择
Android 系统缺陷不完全点评
.net环境下跨进程、高频率读写数据
FFmpeg开发笔记(六十二)Windows给FFmpeg集成H.266编码器vvenc
从零开始学习jQuery (十一) 实战表单验证与自动完成提示插件
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
签约作者
程序园优秀签约作者
发帖
呵烘稿
2025-6-6 09:46:05
关注
0
粉丝关注
12
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
敖可
9986
凶契帽
9992
背竽
9992
4
猷咎
9990
5
裴涛
9990
6
里豳朝
9990
7
处匈跑
9990
8
黎瑞芝
9990
9
松菊
9990
10
段干叶农
9990
查看更多