关于享元模式我所知道的

简介: 关于享元模式我所知道的

image.png


关键词:结构型 享元 FlyWeight 性能优化


什么是享元模式?


享元的本质是通过 共享基础类 来处理大量相同的对象。主要是用于性能优化

先看一个简单案例对享元模式有个概念,

需求:现在需要做50串烤肉,50串烤玉米。一般情况下需要准备100根签子串烤串。

但是今天店里只有两根签子,所以我们只能两根签子这样一批批上。

这就是享元模式,拿时间换内存。

// 签子足够的时候
class Skewers {
  constructor(type, skewerIdx) {
    this.type = type;
    this.skewerIdx = skewerIdx;
  }
  showInfo() {
    console.log(`第${this.skewerIdx}根${this.type}签`);
  }
}
for (let i = 0; i < 50; i++) {
  const m = new Skewers("肉", i + 1);
  m.showInfo();
}
for (let i = 0; i < 50; i++) {
  const f = new Skewers("蔬菜", i + 1);
  f.showInfo();
}
// 场景优化后
class Skewers {
  constructor(type) {
    this.type = type;
  }
  showInfo() {
    console.log(`第${this.skewerIdx}根${this.type}签`);
  }
}
const m = new Skewers("肉");
const f = new Skewers("蔬菜");
for (let i = 0; i < 50; i++) {
  f.skewerIdx = i + 1;
  m.skewerIdx = i + 1;
  f.showInfo();
  m.showInfo();
}


应用场景


判断是否需要使用享元模式:

  • 项目中存在大量重复对象
  • 重复的对象为不可变对象,或者一些属性是不可变的。

总而言之需要达到:复用对象,节省内存 的作用。

前端的话,比如:地图上的 cluster 和 mark 都是常用的场景,和绘图相关的都有可能使用到。


如何实现享元模式?


前提:享元对象是不可变对象。

核心:在内存中只保留一份实例,供多处代码引用。

  1. 将需要改写为享元类属性拆分为两个部分,
  • 内在状态:包含不变的、可在许多对象中重用的部分。
  • 外在状态:包含每个对象各自不同的情景数据的成员变量
  1. 保留类中表示内在状态的属性, 并设置为不可修改。这些属性的值只能在 constructor 中获取。
  2. 找到所有使用外在状态成员变量的方法,为方法中所用的每个成员变量新建一个参数, 并使用该参数代替成员变量。
  3. 创建工厂类来管理享元缓存池,它负责在新建享元时检查已有的享元。


// 享元模式
class Flyweight {
  // 内部状态
  private sharedState: any;
  constructor(sharedState: any) {
    this.sharedState = sharedState;
  }
  // 传入外部状态
  public operation(uniqueState): void {
    const s = JSON.stringify(this.sharedState);
    const u = JSON.stringify(uniqueState);
    console.log(`Flyweight: Displaying shared (${s}) and unique (${u}) state.`);
  }
}
// 工厂方法-生成多个实例
class FlyweightFactory {
  private flyweights: { [key: string]: Flyweight } = <any>{};
  constructor(initialFlyweights: string[][]) {
    for (const state of initialFlyweights) {
      this.flyweights[this.getKey(state)] = new Flyweight(state);
    }
  }
  private getKey(state: string[]): string {
    return state.join("_");
  }
  public getFlyweight(sharedState: string[]): Flyweight {
    const key = this.getKey(sharedState);
    if (!(key in this.flyweights)) {
      console.log(
        "FlyweightFactory: Can't find a flyweight, creating new one."
      );
      this.flyweights[key] = new Flyweight(sharedState);
    } else {
      console.log("FlyweightFactory: Reusing existing flyweight.");
    }
    return this.flyweights[key];
  }
  public listFlyweights(): void {
    const count = Object.keys(this.flyweights).length;
    console.log(`\nFlyweightFactory: I have ${count} flyweights:`);
    for (const key in this.flyweights) {
      console.log(key);
    }
  }
}
// 找到所有使用外在状态成员变量的方法,为在方法中所用的每个成员变量新建一个参数, 并使用该参数代替成员变量。
function addCarToPoliceDatabase(
  ff: FlyweightFactory,
  plates: string,
  owner: string,
  brand: string,
  model: string,
  color: string
) {
  const flyweight = ff.getFlyweight([brand, model, color]);
  flyweight.operation([plates, owner]);
}
const factory = new FlyweightFactory([
  ["Chevrolet", "Camaro2018", "pink"],
  ["Mercedes Benz", "C300", "black"],
  ["Mercedes Benz", "C500", "red"],
  ["BMW", "M5", "red"],
  ["BMW", "X6", "white"],
]);
factory.listFlyweights();
addCarToPoliceDatabase(factory, "CL234IR", "James Doe", "BMW", "M5", "red");
addCarToPoliceDatabase(factory, "CL234IR", "James Doe", "BMW", "X1", "red");
factory.listFlyweights();


参考资料


refactoringguru 享元模式

《JavaScript 设计模式与开发实践》

目录
相关文章
|
JSON JavaScript API
Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)
Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)
|
数据安全/隐私保护
计算机四级网络工程师等级考试题库软件---百度云分享
做件好事,考四级的兄弟们一起共勉~~~ 链接:https://pan.baidu.com/s/1im4BDVZofZbT9f5PZtsxdA 密码:9i5h ​ ​支持一下呗
2760 0
|
机器学习/深度学习 测试技术
ACL杰出论文奖:GPT-4V暴露致命缺陷?JHU等发布首个多模态ToM 测试集,全面提升大模型心智能力
【10月更文挑战第6天】约翰斯·霍普金斯大学等机构提出了一项荣获ACL杰出论文奖的研究,旨在解决大模型在心智理论(ToM)上的不足。他们发布了首个MMToM-QA多模态ToM测试集,并提出BIP-ALM方法,从多模态数据中提取统一表示,结合语言模型进行贝叶斯逆规划,显著提升了模型的ToM能力。这一成果为机器与人类自然交互提供了新思路,尽管仍面临一些局限性和技术挑战。论文详情见:https://arxiv.org/abs/2401.08743。
247 6
|
JavaScript
NodeJs——如何下载文件
NodeJs——如何下载文件
313 4
|
架构师 安全 程序员
软考资料-分享
本文提供了计算机软考资源分享,包括高级、中级和初级三个层次的专业课程。高级课程如系统架构师、网络规划设计师等,中级课程如网络工程师、数据库系统工程师等,初级课程如网络管理员、程序员等,覆盖了多种专业方向,适合不同水平的学习者。
6338 0
|
JavaScript 前端开发 安全
JavaScript函数详解
JavaScript函数的详细解析,包括函数的定义和调用方式(如一般格式、匿名函数、构造函数、自调用函数、箭头函数和严格模式)、函数参数(arguments对象、可变参数、默认参数值)、闭包的概念和应用实例。
JavaScript函数详解
|
测试技术 UED
软件测试中的探索性测试:一种创新的质量保证方法
在软件开发的生命周期中,测试阶段扮演着至关重要的角色。传统的软件测试方法,如自动化测试和回归测试,虽然在一定程度上保证了软件质量,但它们往往依赖于预定义的测试用例和脚本,可能无法覆盖所有用户场景和边缘情况。为了克服这些限制,探索性测试作为一种创新的质量保证方法应运而生。本文将深入探讨探索性测试的概念、优势以及如何有效地实施它,以帮助读者更好地理解和应用这种测试技术。
|
存储 PyTorch API
Pytorch入门—Tensors张量的学习
Pytorch入门—Tensors张量的学习
182 0
|
存储 缓存 监控
内存优化 | Bitmap优化
在内存优化中,优化 Bitmap 占用的内存效果最为明显,在 Android 里面,大部分 OOM,都是 bitmap 占用资源过大导致的,那么问题来了 如何防止 bitmap 占用资源过大导致 OOM?Android 系统何时会发生 OOM?怎样搭建线上线下一体化内存监控体系?Drump 文件过大,我们线上如何查看?线下监控那些工具你会用吗?关于 Native 层的内存泄漏该如何解决?图片监控你做过哪些努力?内存抖动为什么会引起 OOM?内存监控里面采集方式有哪些? 看完本文,希望可以以本文为索引,然后依次排雷解决上述问题,这样你也是这个领域的专家了
674 0
内存优化 | Bitmap优化