一聚教程网:一个值得你收藏的教程网站

热门教程

如何使用JavaScript对象字面量作为享元模式的内部状态高速缓存池

时间:2026-06-24 09:42:47 编辑:袖梨 来源:一聚教程网

JavaScript对象字面量本身不是享元模式的实现,但它可作为享元中不可变内部状态的轻量级存储载体,配合工厂管理与Map缓存池,通过JSON.stringify规范化键实现复用,外部状态则由调用方动态传入。

JavaScript对象字面量本身不是享元模式的实现,但它可以作为享元对象中**内部状态(intrinsic state)的轻量级存储载体**,配合工厂管理、对象复用,高效构建享元池。关键不在于“用字面量代替类”,而在于**把不可变的共享数据固化为字面量,把可变的外部状态剥离出去**。

享元池的核心结构:字面量存内态,函数管复用

享元模式要分离内在状态(共享、不可变)和外在状态(变化、不共享)。对象字面量天然适合表达前者——它轻量、无原型开销、可直接序列化、便于比对与缓存。

  • 把字体样式、图标类型、按钮主题等配置项定义为只读字面量,例如:{ size: 'sm', variant: 'outline', icon: 'check' }
  • 用一个工厂函数统一管理这些字面量实例,避免重复创建相同配置的对象
  • 享元对象本身只保存引用(如 config: configRef),不拷贝字面量内容

用 Map 实现字面量键值化的享元缓存池

不能靠 === 比较两个字面量是否相等(它们总是不同引用),必须将字面量“规范化”后作为缓存键。推荐用 JSON.stringify 或更安全的浅序列化方式生成唯一键。

  • 对字面量做排序 + 序列化,确保 {a:1,b:2}{b:2,a:1} 得到同一 key
  • 缓存池用 Map 存储:pool.set(key, { config, render() { ... } })
  • 每次请求时先查 key,命中则复用,未命中则新建并缓存

外部状态必须彻底解耦,由调用方传入

享元对象绝不持有 id、position、onClick 回调等会变的数据。这些必须作为参数在使用时动态注入。

立即学习“Java免费学习笔记(深入)”;

  • 渲染方法设计为 flyweight.render({ id, x, y, onClick }),而非绑定在实例上
  • 避免在享元内部维护 DOM 引用或事件监听器;所有副作用交由使用者控制
  • 这样同一个字面量配置的享元,可被成百上千个不同位置/行为的 UI 元素复用

实际小例子:图标享元池

假设渲染不同颜色尺寸的 SVG 图标,但 SVG 路径数据固定:

const iconConfigs = {  'home-sm-blue': { size: 16, color: '#1e40af', path: 'M10 20v-6h4v6h5v-8h-3V4h-4v8h-3z' },  'home-lg-red': { size: 24, color: '#dc2626', path: 'M10 20v-6h4v6h5v-8h-3V4h-4v8h-3z' }};const iconPool = new Map();function getIconFlyweight(config) {  const key = JSON.stringify(config);  if (!iconPool.has(key)) {    iconPool.set(key, {      config,      render({ id, x, y }) {        return `<svg id="${id}" x="${x}" y="${y}" width="${config.size}" height="${config.size}">                  <path fill="${config.color}" d="${config.path}"/>                </svg>`;      }    });  }  return iconPool.get(key);}

调用时:getIconFlyweight(iconConfigs['home-sm-blue']).render({id:'i1', x:10, y:20}) —— 内部状态复用,外部状态按需注入。

热门栏目