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

设计模式之备忘录模式

作者: 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