设计模式:备忘录模式

“设计模式”这四个字大家都耳熟能详,那么今天我就来说说其中之一的备忘录模式。
	顾名思义“备忘录”就是为了回到忘记之前记录的地方,专业一点就是:在不破坏对象的封装性的前提下,在对象之外捕获并保存该对象内部的状态以便日后对象使用或者对象恢复到以前的某个状态。 -->

三个角色:
发起人角色:记录当前时刻的内部状态,负责创建和恢复备忘录数据

 备忘录角色:负责存储发起人对象的内部状态,在进行恢复时提供给发起人需要的状态(提供get set方法)
 
 管理者角色:负责保存备忘录对
 
   举例: 备忘录模式比较适用于功能比较复杂的,但是需要维护或记录属性历史,或者需要保存的属性只是众多属性中的一小部分。

该模式可以应用在撤销操作和退回上一页甚至还可以做数据库备份的功能
在JavaScript设计模式这本书中有一个例子说的是查看新闻,在应用备忘录模式之前是这个样子的!

// 事件:下一页
$('#next_page_btn').click(function() {
    // 获取新闻列表容器
    var $news = $('#news_content');
    // 获取当前页号
    var page = $news.data('page');
    // 从服务端获取下一页的列表数据并显示
    getPageDataFromServer(page, function() {
        $news.data('page', page + 1);
    })
});
// 事件:上一页
$('#pre_page_btn').click(function() {
    // 获取新闻列表容器
    var $news = $('#news_content');
    // 获取当前页号
    var page = $news.data('page');
    // 从服务端获取上一页的列表数据并显示
    getPageDataFromServer(page, function() {
        $news.data('page', page - 1);
    });
});

在备忘录模式中主要其作用的部分是缓存器,我们可以将获取到的数据存储在缓存器中在需要的时候取出来展示,下面的代码是缓存器的实现代码:

// Page备忘录
var Page = function() {
    // 缓存器
    var cache = {};
    return function(page, fn) {
        if (cache[page]) {
            // 1-如果缓存中存在指定页的数据,直接使用
            showPage(page, cache[page]);
            fn && fn();
        } else {
            // 2-如果缓存中不存在指定页的数据,则从服务端获取,并将其缓存下来
            $.post('server_api_url', { page: page }, function(res) {
                if (res.success) {
                    showPage(page, res.data);
                    cache[page] = res.data;
                    fn && fn();
                } else {
                    // ajax error
                }
            });
        }
    }
}();

这段代码很明显在下一页和上一页之前都需要调用接口请求数据,再看看应用备忘录模式之后

// 事件:下一页
$('#next_page_btn').click(function() {
  // 获取新闻列表容器
  var $news = $('#news_content');
  // 获取当前页号
  var page = $news.data('page');
  Page(page, function() {
    $news.data('page', page+1);
  });
});
// 事件:上一页
$('#pre_page_btn').click(function() {
  // 获取新闻列表容器
  var $news = $('#news_content');
  // 获取当前页号
  var page = $news.data('page');
  Page(page, function() {
    $news.data('page', page-1);
  });
});

应用备忘录模式之后代码好像更多了,因为这是小的应用如果在大型应用中效果会很明显,试想一个大项目中有一个接口返回的数据是几百兆,每次返回上一步都需要去获取这几百兆的数据其不是很浪费资源更影响系统性能。

下面有个小例子来展示以下备忘录模式的应用:

var GameRole = function(){

        //角色状态存储箱
        var roleStateMemento = {};
        
        this.getMemento = function(){
            return roleStateMemento;
        };

        this.setMemento = function(memento){
            roleStateMemento = memento;
        };

        this.getInitState();
    };
    //状态显示
    GameRole.prototype.stateDisplay = function(){
        console.log('角色当前状态:');
        console.log('体力:' + this.vitality);
        console.log('攻击力:' + this.attack);
        console.log('防御力:' + this.defense);
    };
    //保存角色状态
    GameRole.prototype.saveState = function(){
        this.setMemento({
            vitality:this.vitality,
            attack:this.attack,
            defense:this.defense
        });
    };
    //恢复角色状态
    GameRole.prototype.recoveryState = function(){
        var memento = this.getMemento();
        this.vitality = memento.vitality;
        this.attack = memento.attack;
        this.defense = memento.defense;
    };
    //获得初始状态
    GameRole.prototype.getInitState = function(){
        this.vitality = 100;
        this.attack = 100;
        this.defense = 100;
    };
    //战斗
    GameRole.prototype.fight = function(){
        this.vitality = 0;
        this.attack = 0;
        this.defense = 0;
    };


    //调用:
    //
    //大战Boss前
    var gr = new GameRole();
    gr.stateDisplay();

    //保存进度
    gr.saveState();

    //大战Boss时,损耗严重
    gr.fight();
    gr.stateDisplay();

    //恢复之前状态
    gr.recoveryState();
    gr.stateDisplay();

以上就是备忘录模式的讲解以及简单应用。

posted @ 2021-12-24 17:19  leayun  阅读(44)  评论(0)    收藏  举报