JavaScript设计模式总结-享元模式

享元(flyweight)模式的主要作用:性能优化

当系统创建过多相似的对象而导致内存占用过高,可以采用这种设计模式进行优化。

享元模式将对象的属性区分为内部状态外部状态

内部状态在创建的时候赋值,外部状态在实际需要用到的时候进行动态赋值

对于内部状态和外部状态的区分,有2点:

1、内部状态存储于对象内部

2、内部状态可以被一些对象共享

3、内部状态独立于具体场景,通常不会改变

4、外部状态取决于具体场景,并根据场景变化,外部状态不能被共享。

举例

1、男女模特试衣服

若为每个模特对象Model均设置性别sex,underwear两个属性,每次试衣均创建了一次对象,会导致过多的对象。

由享元模式优化后,Model对象仅sex一个属性,而underwear属性在需要的时候才进行赋值

const Model = function(sex) {
  this.sex = sex;
}
Model.prototype.takePhoto = function() {
  console.log(‘sex= ‘ + this.sex + ‘underwear‘ + this.underwear);
}
const maleModel = new Model(‘male‘);
const femaleModel = new Model(‘female‘);
for(let i = 1; i <= 50; i++) {
  maleModel.underwear = ‘underwear‘ + i;
  femaleModel.takePhoto();
}
for(let j = 1; j <= 50; j++) {
  femaleModel.underwear = ‘underwear‘ + j;
  femaleModel.takePhoto();
}

2、文件上传

为优化前

let id = 0;
window.startUpload = function(uploadType, files) {
  for(let i = 0, file; file = files[i++];) {
    const uploadObj = new Upload(uploadType, file.fileName, file.fileSize);
    uploadObj.init(id++);
  }
}

const Upload = function(uploadType, fileName, fileSize) {
  this.uploadType = uploadType;
  this.fileName = fileName;
  this.fileSize = fileSize;
  this.dom = null;
}
Upload.prototype.init = function(id) {
  this.id = id;
  this.dom = document.createElement(‘div‘);
  ...创建上传成功的fileName和fileSize相关展示DOM、绑定删除事件delFile()、插入DOM
}
Upload.prototype.delFile = function() {
  ...删除DOM节点及对象
}

调用

startUpload(‘plugin‘, [
  {
    fileName: ‘1.txt‘,
    fileSize: 1000,
  },
  {
    fileName: ‘2.txt‘,
    fileSize: 3000,
  },
  {
    fileName: ‘3.txt‘,
    fileSize: 5000,
  },
]);

用享元模式优化后

const Upload = function(uploadType) {
  this.uploadType = uploadType;
}
Upload.prototype.delFile = function(id) {
  uploadManager.setExternalState(id, this);
  ...删除DOM
}
const UploadFactory = (function() {
  const createdFlyWeightObjs = {};
  return {
    create(uploadType) {
      if (createdFlyWeightObjs[uploadType]) {
        return createdFlyWeightObjs[uploadType];
      }
      return createdFlyWeightObjs[uploadType] = new Upload(uploadType);
    }
  }
})();
const uploadManager = (function() {
  const uploadDatabase = {};
  return {
    add(id, uploadType, fileName, fileSize) {
      // 仅仅创建基本type
      const flyWeightObj = UploadFactory.create(uploadType);

      ...添加展示的DOM和相应的删除事件delFile()

      // 存放额外的属性,通过调用 setExternalState() 函数将以下属性赋值到flyWeightObj上
      uploadDatabase[id] = {
        fileName,
        fileSize,
        dom,
      };
      return flyWeightObj;
    },
    setExternalState(id, flyWeightObj) {
      const uploadData = uploadDatabase[id];
      for(const i in uploadData) {
        flyWeightObj[i] = uploadData[i];
      }
    },
  }
})();
// 开始出发上传动作的startUpload函数
let id = 0;
window.startUpload = function(uploadType, files) {
  for(let i = 0, file; file = files[i++];) {
    const uploadObj = uploadManager.add(++id, uploadType, file.fileName, file.fileSize);
  }
}
// 使用
startUpload(‘plugin‘, [
  {
    fileName: ‘1.txt‘,
    fileSize: 1000,
  },
  {
    fileName: ‘2.txt‘,
    fileSize: 3000,
  },
  {
    fileName: ‘3.txt‘,
    fileSize: 5000,
  },
]);

对象池示例

页面上要动态创建、删除DOM节点,可以将创建的DOM用完后存放在内存中,需要的时候直接拿出来,而不是再创建

const objectPoolFactory = function(createObjFn) {
  const objectPool = [];
  return {
    create() {
      const obj === objectPool.length ?
            createObjFn.apply(this, arguments) : objectPool.shift();
      return obj;
    }
    recover(obj) {
      objectPool.push(obj);
    }
  }
}

const iframeFactory = objectPoolFactory(function() {
  const iframe = document.createElement(‘iframe‘);
  document.body.appendChild(iframe);

  iframe.onload = function() {
    iframe.onload = null;
    iframeFactory.recover(iframe);
  }
  return iframe;
});

const iframe1 = iframeFactory.create();
iframe1.src = ‘http://baidu.com‘;

const iframe2 = iframeFactory.create();
iframe2.src = ‘http://QQ.com‘;

参考文献:

[1] 《JavaScript设计模式与开发时间》,曾探,中国工信出版集团.

原文地址:https://www.cnblogs.com/yijingzheng/p/10367101.html

时间: 2024-10-12 15:56:29

JavaScript设计模式总结-享元模式的相关文章

深入理解JavaScript系列(37):设计模式之享元模式

介绍 享元模式(Flyweight),运行共享技术有效地支持大量细粒度的对象,避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类). 享元模式可以避免大量非常相似类的开销,在程序设计中,有时需要生产大量细粒度的类实例来表示数据,如果能发现这些实例除了几个参数以外,开销基本相同的 话,就可以大幅度较少需要实例化的类的数量.如果能把那些参数移动到类实例的外面,在方法调用的时候将他们传递进来,就可以通过共享大幅度第减少单个实例 的数目. 那么如果在JavaScript中应用享元模式

设计模式之享元模式

Flyweight在拳击比赛中指最轻量级,即"蝇量级"或"雨量级",这里选择使用"享元模式"的意译,是因为这样更能反映模式的用意.享元模式是对象的结构模式.享元模式以共享的方式高效地支持大量的细粒度对象. Java中的String类型 在JAVA语言中,String类型就是使用了享元模式.String对象是final类型,对象一旦创建就不可改变.在JAVA中字符串常量都是存在常量池中的,JAVA会确保一个字符串常量在常量池中只有一个拷贝.Stri

纵横之设计模式(享元模式-性能与对象访问)

声明:本系列文章内容摘自<iOS设计模式> 享元模式:运用共享技术有效地支持大量细粒度的对象. 何为享元模式 实现享元模式需要两个关键组件,通常是可共享的享元对象和保存它们的池.某种中央对象维护这个池,并从它返回适当的实例,工厂是这一角色的理想候选.它可以通过一个工厂方法,根据父类型返回各种类型的具体享元对象.其主要目的就是维护池中的享元对象,并适当的从中返回享元对象. 何时使用享元模式 1.应用程序使用很多对象: 2.在内存中保存对象会影响内存性能: 3.对象的多处持有状态(外在状态)可以放

Java设计模式之享元模式实例详解

本文实例讲述了Java设计模式之享元模式.分享给大家供大家参考,具体如下: 解释一下概念:也就是说在一个系统中如果有多个相同的对象,那么只共享一份就可以了,不必每个都去实例化一个对象.比如说一个文本系统,每个字母定一个对象,那么大小写字母一共就是52个,那么就要定义52个对象.如果有一个1M的文本,那么字母是何其的多,如果每个字母都定义一个对象那么内存早就爆了.那么如果要是每个字母都共享一个对象,那么就大大节约了资源. 在Flyweight模式中,由于要产生各种各样的对象,所以在Flyweigh

Head First设计模式之享元模式(蝇量模式)

一.定义 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式. 享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象.我们将通过创建 5 个对象来画出 20 个分布于不同位置的圆来演示这种模式.由于只有 5 种可用的颜色,所以 color 属性被用来检查现有的 Circle 对象. 二.结构 三.实现 namespace DesignPattern

设计模式:享元模式(Flyweight)

?运用共享技术有效地支持大量细粒度的对象.又名"蝇量模式". ?在Java语言中,String类型就是使用了享元模式.String对象是final类型,对象一旦创建就不可改变.在JAVA中字符串常量都是存在常量池中的,Java会确保一个字符串常量在常量池中只有一个拷贝.譬如: String a = "abc"; String b = "abc"; System.out.println(a==b); ?输出结果:true.这就说明了a和b量引用都指

设计模式之享元模式--- Pattern Flyweight

模式的定义 享元模式(Flyweight Pattern)是沲技术的重要实现方式,其定义如下: Use sharing to support large numbers of fine-grained objects efficiently. 使用共享对象可有效地支持大量的细粒度的对象. 享元模式的定义提出了二个要求:细粒度的对象和共享对象.分配太多的对象将有损程序的性能,同时还容易造成内存溢出.避免这种情况,就是使用享元模式中的共享技术. 细粒度的状态分为内部状态(instrinsic)和外部

设计模式-12 享元模式(结构型模式)

一 享元模式 享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用. 主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建. 关键代码:存储相似的对象 使用场景: 1.系统有大量相似对象. 2.需要缓冲池的场景. 类图 : 二 实现代码 Java里面的JDBC连接池,适用于作共享的一些个对象,他们有一些共有的属性,就拿数据库连接 池来说,url.driv

JS常用的设计模式(16)—— 享元模式

享元模式主要用来减少程序所需的对象个数. 有一个例子, 我们这边的前端同学几乎人手一本<JavaScript权威指南>. 从省钱的角度讲, 大约三本就够了. 放在部门的书柜里, 谁需要看的时候就去拿, 看完了还回去. 如果同时有4个同学需要看, 此时再去多买一本. 在webqq里面, 打开QQ好友列表往下拉的时候,会为每个好友创建一个div( 如果算上div中的子节点, 还远不只1个元素 ). 如果有1000个QQ好友, 意味着如果从头拉到尾, 会创建1000个div, 这时候有些浏览器也许已