JavaScript对象字面量本身不是享元模式的实现,但它可作为享元中不可变内部状态的轻量级存储载体,配合工厂管理与Map缓存池,通过JSON.stringify规范化键实现复用,外部状态则由调用方动态传入。
JavaScript对象字面量本身不是享元模式的实现,但它可以作为享元对象中**内部状态(intrinsic state)的轻量级存储载体**,配合工厂管理、对象复用,高效构建享元池。关键不在于“用字面量代替类”,而在于**把不可变的共享数据固化为字面量,把可变的外部状态剥离出去**。
享元模式要分离内在状态(共享、不可变)和外在状态(变化、不共享)。对象字面量天然适合表达前者——它轻量、无原型开销、可直接序列化、便于比对与缓存。
config: configRef),不拷贝字面量内容不能靠 === 比较两个字面量是否相等(它们总是不同引用),必须将字面量“规范化”后作为缓存键。推荐用 JSON.stringify 或更安全的浅序列化方式生成唯一键。
{a:1,b:2} 和 {b:2,a:1} 得到同一 keyMap 存储:pool.set(key, { config, render() { ... } })
享元对象绝不持有 id、position、onClick 回调等会变的数据。这些必须作为参数在使用时动态注入。
立即学习“Java免费学习笔记(深入)”;
flyweight.render({ id, x, y, onClick }),而非绑定在实例上假设渲染不同颜色尺寸的 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}) —— 内部状态复用,外部状态按需注入。