美文网首页程序员简友广场想法
设计模式之备忘录模式

设计模式之备忘录模式

作者: Splendid飞羽 | 来源:发表于2020-09-25 19:11 被阅读0次

# 什么是备忘录模式

备忘录模式:属于行为模式,保存某个状态,并且在需要的时候直接获取,而不是重复计算
意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

注意:备忘录模式实现,不能破坏原始封装。也就是说,能拿到内部状态,将其保存在外部。

# 应用场景

最典型的例子是“斐波那契数列”递归实现。
不借助备忘录模式,数据一大,就容易爆栈;借助备忘录,算法的时间复杂度可以降低到O(N)

除此之外,数据的缓存等也是常见应用场景。

  • 备忘录模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。
  • 如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态。
  • 使用备忘录可以把复杂的对象内部信息对其他的对象屏蔽起来,当角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。

介绍完备忘录模式的定义之后,下面具体看看备忘录模式的结构图:

image

备忘录模式中主要有三类角色:

  • 发起人角色:记录当前时刻的内部状态,负责创建和恢复备忘录数据。
  • 备忘录角色:负责存储发起人对象的内部状态,在进行恢复时提供给发起人需要的状态。
  • 管理者角色:负责保存备忘录对象。
    比较简单的案例可以参考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

相关文章

网友评论

    本文标题:设计模式之备忘录模式

    本文链接:https://www.haomeiwen.com/subject/iqagyktx.html