享元模式(Flyweight)是一种软件设计模式.是通过将类似的对象进行共享,达到最小化内存的使用对象.
享元模式要求将对象的属性划分为内部状态(不会改变属性)和外部状态(会动态变化的属性).享元模式的目标是尽量减少共享对象的数量.它的关键点是划分内部状态和外部状态.
享元模式特点:
- 内部状态存储于对象内部
- 内部状态可以被一些对象共享
- 内部状态独立于具体的场景,通常不会变化
- 外部状态取决于具体的场景,并根据场景而变化,外部状态不会被共享.
注意: 享元模式是一种用时间换空间的优化模式.
例子
PC端的文件上传组件.文件上传有多种方式,相同的方式可以通过一个对象来完成,而不用根据调用次数创建多个类型相同的对象.
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 46 47 48 49 50 51 52 53 54 55 56 57 58
| var UploadFactory = (function () { var createFlyWeightObjs = {}; return { create (upload) { if (createdFlyWeightObjs[uploadType]) { return createdFlyWeightObjs[uploadType]; } return createdFlyWeightObjs[uploadType] = new Upload(uploadType); } } })
var Upload = function (uploadType) { this.uploadType = uploadType } Upload.prototype.delFile = function (id) { uploadManager.setExternalState(id, this); this.dom.parentNode.removeChild(this.dom); }
var uploadManager = (function () { var uploadDatabase = {}; return { add (id, uploadType, fileName, fileSize) { var flyWeightObj = UploadFactory.create(uploadType); dom.innerHTML = `<span>文件件名词: ${fileName},文件大小:${fileSize}</span>`+ `<button class="delFile">删除</button>`; dom.querySelector('.delFile').onclick = function () { flyWeightObj.delFile(id); } document.body.applendChild(dom); uploadDatabase[id] = { fileName, fileSize, dom }; return flyWeightObj; }, setExternalState (id, flyWeightObj) { var uploadData = uploadDatabase[id]; for(let i in uploadData) { flyWeightObj[i] = uploadData[i]; } } } })();
window.startUpload = function (uploadType, files) { for(let i = 0, file; file = files[i++]) { var uploadObj = uploadManage.add(++id, uploadType, file.fileName, file.fileSize); }) }
startUpload('plugin', [{fileName: '1.text',fileSize: 1000},{fileName: '2.png', fileSize: 1900}])
startUpload('flash', [{fileName: '3.text',fileSize: 1000},{fileName: '4.png', fileSize: 1900}])
|
适用范围
- 一个程序中使用大量相似的对象
- 由于使用了大量对象,造成很大的内存开销
- 对象的大多数状态都可以变为外部状态
- 剥离出对象的外部状态之后,可以用相对较少的共享对象取代大量的对象.
对象池
对象池模式(object pool pattern)和享元模式有些相识.都是将共享对象节省创建对象的开销.
不同的是,对象池是将已经创建的对象集中在一起,当有地方需要的时候,从它这里获取对象使用.当对象使用完成后,再归还给对象池.
对象池(英语:object pool pattern)是一种设计模式。一个对象池包含一组已经初始化过且可以使用的对象,而可以在有需求时创建和销毁对象。池的用户可以从池子中取得对象,对其进行操作处理,并在不需要时归还给池子而非直接销毁它。这是一种特殊的工厂对象。
例子
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
| var objectPoolFactory = function (createObjFn) { var objectPool = []; return { create () { var obj = objectPool.length === 0? createObjFn.apply(this, arguments): objectPool.shift(); return obj }, recover (obj) { objectPool.push(obj); } } };
var iframeFactory = objectPoolFactory(function () { var iframe = document.createElement('iframe'); document.body.appendChild(iframe); iframe.onload = function () { iframe.onload = null; iframeFactory.recover(iframe); } return iframe; }); var iframe1 = iframeFactory.create(); iframe1.src = 'http://google.com';
var iframe2 = iframeFactory.create(); iframe1.src = 'http://facebook.com';
setTimeout(() => { var iframe2 = iframeFactory.create(); iframe1.src = 'http://youtube.com'; }, 1000)
|