专栏首页YuanXin设计模式 - 备忘录模式 - JavaScript

设计模式 - 备忘录模式 - JavaScript

备忘录模式:属于行为模式,保存某个状态,并且在需要的时候直接获取,而不是重复计算

专注前端与算法的系列干货分享。 引用请声明:xxoo521.com | 「公众号:心谭博客」

什么是备忘录模式

备忘录模式:属于行为模式,保存某个状态,并且在需要的时候直接获取,而不是重复计算

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

应用场景

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

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

多语言实现

ES6 实现

首先模拟了一下简单的拉取分页数据。 如果当前数据没有被缓存,那么就模拟异步请求,并将结果放入缓存中; 如果已经缓存过,那么立即取出即可,无需多次请求。

main.js

const fetchData = (() => {
    // 备忘录 / 缓存
    const cache = {};

    return page =>
        new Promise(resolve => {
            // 如果页面数据已经被缓存, 直接取出
            if (page in cache) {
                return resolve(cache[page]);
            }
            // 否则, 异步请求页面数据
            // 此处, 仅仅是模拟异步请求
            setTimeout(() => {
                cache[page] = `内容是${page}`;
                resolve(cache[page]);
            }, 1000);
        });
})();

// 以下是测试代码
const run = async () => {
    let start = new Date().getTime(),
        now;
    // 第一次: 没有缓存
    await fetchData(1);
    now = new Date().getTime();
    console.log(`没有缓存, 耗时${now - start}ms`);

    // 第二次: 有缓存 / 备忘录有记录
    start = now;
    await fetchData(1);
    now = new Date().getTime();
    console.log(`有缓存, 耗时${now - start}ms`);
};

run();

最近在项目中还遇到一个场景,在React中加载微信登陆二维码。 这需要编写一个插入script标签的函数。

要考虑的情况是:

  1. 同一个script标签不能被多次加载
  2. 对于加载错误,要正确处理
  3. 对于几乎同时触发加载函数的情况, 应该考虑锁住

基于此,main2.js文件编码如下:

// 备忘录模式: 防止重复加载
const loadScript = src => {
    let exists = false;

    return () =>
        new Promise((resolve, reject) => {
            if (exists) return resolve();
            // 防止没有触发下方的onload时候, 又调用此函数重复加载
            exists = true;
            // 开始加载
            let script = document.createElement("script");
            script.src = src;
            script.type = "text/javascript";
            script.onerror = ev => {
                // 加载失败: 允许外部再次加载
                script.remove();
                exists = false;
                reject(new Error("Load Error"));
            };
            script.onload = () => {
                // 加载成功: exists一直为true, 不会多次加载
                resolve();
            };
            document.body.appendChild(script);
        });
};

/************** 测试代码 **************/
// 专门用于加载微信SDK的代码
const wxLoader = loadScript(
    "https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.jser"
);
// html中只有1个微信脚本
setInterval(() => {
    wxLoader()
        .then()
        .catch(error => console.log(error.message));
}, 5000);

index2.html中引入上述代码,即可查看效果:

<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Documenttitle>
    head>
    <body>
        <script src="./main2.js">script>
    body>
html>

python3 实现

这里实现一下借助“备忘录模式”优化过的、递归写法的“斐波那契数列”。

def fibonacci(n):
  # 结果缓存
  mem = {1: 1, 2: 1}

  def _fibonacci(_n):
    # 是否缓存
    if _n in mem:
      return mem[_n]
    mem[_n] = _fibonacci(_n - 1) + _fibonacci(_n - 2)
    return mem[_n]

  return _fibonacci(n)

if __name__ == '__main__':
  print(fibonacci(999))

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • NodeJS模块研究 - fs

    node 的fs文档密密麻麻的 api 非常多,毕竟全面支持对文件系统的操作。文档组织的很好,操作基本分为文件操作、目录操作、文件信息、流这个大方面,编程方式也...

    心谭博客
  • 设计模式 - 单例模式 - JavaScript

    如果一个类负责连接数据库的线程池、日志记录逻辑等等,此时需要单例模式来保证对象不被重复创建,以达到降低开销的目的。

    心谭博客
  • 标签应用和版本管理

    当一个代码仓库进过长时间的迭代,针对不同的时期和需求,必定会有不同的版本。而借助 Git 提供的标签功能,可以快捷方便地记录代码版本。无论什么时候,想取回某个版...

    心谭博客
  • ECCV2020 | 将投票机制引入自下而上目标检测,整合局部和全局信息

    本论文收录于ECCV2020,从自下而上的角度出发,在目标检测任务中引入了投票机制,使得HoughNet能够集成近距离和远距离的class-conditiona...

    AI科技评论
  • 两分钟掌握FrameLayout帧布局

    前面学习了线性布局、相对布局、表格布局,那么本期来学习第四种布局——FrameLayout帧布局。 一、认识FrameLayout 帧布局是An...

    分享达人秀
  • 了解Python及python的安装及启

    为什么python使用这么多? python语法简单,上手容易,精通难。现在使用爬虫比较多,还可以作前端。 ##########################...

    py3study
  • WeTest&TesterHome移动测试沙龙【第6期 广州站】精彩分享

    2017年3月25日,腾讯WeTest在广州腾讯微信总部举办了系列移动测试沙龙第6期。本次联合沙龙,是由腾讯WeTest发起,与优质社区TesterHome联...

    WeTest质量开放平台团队
  • 【Git实战技巧】恢复被强制推送push失踪的代码

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    后端技术漫谈
  • 【Git实战技巧】恢复被强制推送push失踪的代码

    Git是一个易学难精的分布式版本控制系统,被我们码农常用于代码的管理。如果你还不了解Git,建议先通过廖雪峰的Git教程进行了解,再来看本文,因为本文以使用技巧...

    Rude3Knife的公众号
  • 经典Bug永流传---每周一“虫”(四)

    SEO优化主要包括title、keywords、description这个三个关键词,但一般企业都基本不重视这个,那么小编分享一下title、keywords、...

    厦门-安仔

扫码关注云+社区

领取腾讯云代金券