# 什么是备忘录模式
备忘录模式:属于行为模式,保存某个状态,并且在需要的时候直接获取,而不是重复计算。
意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
注意:备忘录模式实现,不能破坏原始封装。也就是说,能拿到内部状态,将其保存在外部。
# 应用场景
最典型的例子是“斐波那契数列”递归实现。
不借助备忘录模式,数据一大,就容易爆栈;借助备忘录,算法的时间复杂度可以降低到
除此之外,数据的缓存等也是常见应用场景。
- 备忘录模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。
- 如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态。
- 使用备忘录可以把复杂的对象内部信息对其他的对象屏蔽起来,当角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
介绍完备忘录模式的定义之后,下面具体看看备忘录模式的结构图:
![](https://img.haomeiwen.com/i1413261/ec76c94629c96182.png)
备忘录模式中主要有三类角色:
- 发起人角色:记录当前时刻的内部状态,负责创建和恢复备忘录数据。
- 备忘录角色:负责存储发起人对象的内部状态,在进行恢复时提供给发起人需要的状态。
-
管理者角色:负责保存备忘录对象。
比较简单的案例可以参考vue源码中的缓存函数的写法
/**
* Create a cached version of a pure function.
*/
function cached(fn) {
var cache = Object.create(null);
return (function cachedFn(str) {
var hit = cache[str];
return hit || (cache[str] = fn(str))
})
}
/**
* Capitalize a string.
*/
var capitalize = cached(function (str) {
return str.charAt(0).toUpperCase() + str.slice(1)
});
let str = capitalize('sliderUp'); // SliderUp
console.log(str);
let add = function(a) {
return a + 1
}
let adder = cached(add)
adder(1)
adder(1)
adder(2) // 3 cache: { '[1]': 2, '[2]': 3 }
备忘录模式在分页插件中的应用
var Page = function(){
let page = 1,
cache = {},
data;
return function( page ){
if ( cache[ page ] ){
data = cache[ page ];
render( data );
}else{
Ajax.send( 'cgi.xx.com/xxx', function( data ){
cache[ page ] = data;
render( data );
});
}
}
}();
通过cache对象缓存,当请求的数据缓存 过的时候,下次请求直接从缓存中取,不用重新请求,可以加快数据渲染视图。
稍微来看一个复杂一点的案例
备忘录模式实现一个简单的状态机,用于状态的保存,回退。
// 备忘类
class Memento {
constructor(content) {
this.content = content;
}
getContent() {
return this.content;
}
}
// 备忘列表
class CarTaker {
constructor() {
this.list = [];
}
add(memento) {
this.list.push(memento);
}
get(index) {
return this.list[index];
}
getList() {
return this.list
}
}
// 编辑器
class Editor {
constructor() {
this.content = null;
}
setContent(content) {
this.content = content;
}
getContent() {
return this.content;
}
saveContentToMemento() {
return new Memento(this.content);
}
getConentFromMemento(memento) {
this.content = memento.getContent();
}
}
// 测试代码
let editor = new Editor()
let careTaker = new CarTaker()
editor.setContent('111')
editor.setContent('222')
careTaker.add(editor.saveContentToMemento()) // 将当前222内容备份
editor.setContent('333')
careTaker.add(editor.saveContentToMemento()) // 将当前333内容备份
editor.setContent('444')
console.log(editor.getContent())
editor.getConentFromMemento(careTaker.get(1)) // 撤销
console.log(editor.getContent())
editor.getConentFromMemento(careTaker.get(0)) // 撤销
console.log(editor.getContent())
这个例子里面编辑器Editor称为原发器,可以通过saveContentToMemento创建一个备忘录,存储当前状态。Memento是一个备忘录对象,只供原发器使用,提供状态提取方法。CareTaker称之为负责人也可以叫管理者,它负责保存备忘录,但是不能对备忘录内容进行操作或检查
https://www.cnblogs.com/hpx2020/p/10730761.html
http://www.isjs.cn/?p=998
网友评论