• JavaScript设计模式:享元模式


    享元模式

    享元(flyweight)模式是一种用于性能优化的模式,享元模式的核心就是运用共享技术来有效支持大量细粒度的对象。
    享元模式要求将对象的属性划分为内部状态与外部状态(状态在这里通常指属性)。
    享元模式的目标是尽量减少共享对象的数量,关于如何划分内部状态和外部状态

    例子:假设有个内衣工厂,目前的产品有50种男式内衣和50种女士内衣,为了推销产品,工厂决定生产一些塑料模特来穿上他们的内衣拍成广告照片。正常情况下需要50个男模特和50个女模特,然后让他们每人分别穿上一件内衣来拍照。

    const ModelT = function (sex) {
      this.sex = sex;
    };
    
    ModelT.prototype.takePhoto = function () {
      console.log('sex= ' + this.sex + 'underwear = ' + this.underwear);
    };
    
    let maleModel = new ModelT('male');
    let femaleModel = new ModelT('female');
    
    for (var i = 1; i <= 50; i++) {
      maleModel.underwear = 'underwear' + i;
      maleModel.takePhoto();
    };
    
    for (var i = 1; i <= 50; i++) {
      femaleModel.underwear = 'underwear' + i;
      femaleModel.takePhoto();
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    怎样划分内部状态和外部状态?

    ❏ 内部状态存储于对象内部。
    ❏ 内部状态可以被一些对象共享。
    ❏ 内部状态独立于具体的场景,通常不会改变。
    ❏ 外部状态取决于具体的场景,并根据场景而变化,外部状态不能被共享。

    对象池例子

    对象池维护一个装载空闲对象的池子,如果需要对象的时候,不是直接new,而是转从对象池里获取。如果对象池里没有空闲对象,则创建一个新的对象,当获取出的对象完成它的职责之后,再进入池子等待被下次获取。

    // 先定义一个获取小气泡节点的工厂,作为对象池的数组成为私有属性被包含在工厂闭包里,这个工厂有两个暴露对外的方法,create表示获取一个div节点,recover表示回收一个div节点
    var toolTipFactory = (function () {
      var toolTipPool = []; // toolTip对象池
      // console.log('toolTipPool',toolTipPool);
    
      return {
        create: function () {
          if (toolTipPool.length === 0) { //如果对象池为空
            var div = document.createElement('div'); //创建一个domdocument.body.appendChild( div );
            return div;
          } else { //如果对象池里不为空
            return toolTipPool.shift(); //则从对象池中取出一个dom
          }
        },
        recover: function (tooltipDom) {
          return toolTipPool.push(tooltipDom); //对象池回收dom
        }
      }
    
    })();
    
    var ary = [];
    
    // 目前需要创建2个小气泡节点,为了方便回收,用一个数组ary来记录它们:
    for (var i = 0, str; str = ['A', 'B'][i++];) {
      var toolTip = toolTipFactory.create();
      toolTip.innerHTML = str;
      ary.push(toolTip);
    };
    
    // 假设需要重新绘制,在此之前要把这两个节点回收进对象池
    for (var i = 0, toolTip; toolTip = ary[i++];) {
      toolTipFactory.recover(toolTip);
    };
    
    // 再创建6个小气泡
    var aryB = []
    for (var i = 0, str; str = ['A', 'B', 'C', 'D', 'E', 'F'][i++];) {
    
      var toolTip = toolTipFactory.create();
      toolTip.innerHTML = str;
      aryB.push(toolTip);
    
    };
    console.log('aryB', aryB);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    在什么情况下使用享元模式?

    ❏ 一个程序中使用了大量的相似对象。
    ❏ 由于使用了大量对象,造成很大的内存开销。
    ❏ 对象的大多数状态都可以变为外部状态。
    ❏ 剥离出对象的外部状态之后,可以用相对较少的共享对象取代大量对象。

  • 相关阅读:
    KILM: Knowledge Injection into Encoder-Decoder Language Models
    5 - 2 单选题
    SpringBoot+Redis BitMap 实现签到与统计功能
    LeetCode 第113 双周赛补题
    C语言字符函数
    SequoiaDB湖仓一体分布式数据库2022.11月刊
    gcc对void型指针的类型检查有问题?
    二分算法(超详细)
    前端架构-分层而治,铁打的MV流水的C
    Springboot - 15.二级分布式缓存集成-Caffeine
  • 原文地址:https://blog.csdn.net/weixin_40119412/article/details/125964118