js享元模式

享元模式是一种性能优化模式,其核心是运用共享技术来有效的支持大量细粒度的对象。如果系统中因为创建大量类似的对象而导致内存占用过高,那么享元模式就非常有用了。享元模式的目标是尽量减少共享对象的数量。
一、那么什么是享元模式呢?
享元模式要求将对象的属性划分为内部状态和外部状态。那如何划分外部状态和内部状态呢?
1、内部状态存储于对象内部;内部状态可以被一些对象共享;内部状态独立于具体的场景,通常不会改变。
2、外部状态取决于具体的场景,并根据场景而变化,外部状态不被共享。
内部状态相同的对象指定为同一对象,而外部状态可以从同一对象的身上分开,并存储在外部的对象身上。内部状态有多少种情况,系统中便存在多少个对象。
使用享元模式的关键在于如何区分外部状态和内部状态。
二、享元模式的通用结构
1、当对象被需要的时候才创建,所以需要一个对象工厂来创建对象。
2、对象外部状态的管理器来记录对象相关的外部状态。
3、对象本身保存内部状态。
接下来看一段代码:

		//抛离外部状态的对象
		var Upload=function(uploadType){
			this.uploadType=uploadType;
		}
		Upload.prototype.delFile= function(id){
			uploadManager.setExternalState(id,this);
			if(this.fileSize<3000){
				return this.dom.parentNode.removeChild(this.dom);
			}
			if(window.confirm('确定要删除该文件嘛?'+this.fileName)){
				return this.dom.parentNode.removeChild(this.dom);
			}
		}
		//创建对象--工厂对象单例模式
		var UploadFactory=(function(){
			var createdFlyWeightObjs={};
			return  {
				create:function(uploadType){
					if(createdFlyWeightObjs[uploadType]){
						return createdFlyWeightObjs[uploadType]
					}
					return createdFlyWeightObjs[uploadType]=new Upload();
				}
			}
		})();
		//对象外部管理器
		var uploadManager=(function(){
			var uploadDatabase={};
			return {
				add:function(id,uploadType,fileName,fileSize){
					var flyWeightObj=UploadFactory.create(uploadType);
					var dom=document.createElement('div');
					var str=`
						<span>文件名称${fileName}</span>
						<span>文件大小${fileSize}</span>
						<span class="delFile">删除</span>
						`;
					document.body.innerHTML=str;
						dom.querySelector('.delFile').onclick=function(){
						flyWeightObj.delFile(id)
						};
						document.body.appendChild(dom);
						//保存对象的信息,便于外部使用
						uploadDatabase[id]={
							fileName:fileName,
							fileSize:fileSize,
							dom:dom
						};
						return flyWeightObj;
				},
				setExternalState:function(id,flyWeightObj){
					var uploadData=uploadDatabase;
					for(var i in uploadData){
						flyWeightObj[i]=uploadData[i];
					}
				}
			}
		}())

享元模式的适用:
1、一个程序中使用大量的相似的对象
2、由于使用大量的对象,造成大的内存开销
3、对象的大多数状态可变成外部状态
4、抛离外部状态之后可以相对较少的共享对象取代大量对象。

那如果没有外部状态和内部状态的享元呢?
1、没有内部状态的享元其实就是一个唯一的一个共享对象,那么就用单例模式来创建对象,对象的外部管理器不发生改变。
2、没有外部状态我们就要学习对象池
什么是对象池?
对象池维护一个装载空闲对象的池子,如果需要对象的时候,不是直接new,而是转从对象池里获取,如果对象池里没有空闲的对象,则创建一个新的对象,当获取出的对象完成它的职责之后,再进入池子等待被下次获取。
web前端开发,对象池用于最多的就是跟DOM节点有关的操作。比如分页的DOM生成。如何避免频繁的创建和删除DOM节点。
对象池是另一种性能优化方案,它和享元模式一些相似,但并不区分外部内部状态这个过程。

//例子:
var tool=(function(){
			var arr=[];
			return{
				create:function(){
					if(tool.length===0){
						var div=document.createElement('div');
						document.body.appendChild(div);
						return div;
					}else{
						return arr.shift();
					}
				},
				recover:function(dom) {
					return arr.push(dom);
				}
			}
		}());
		var ary=[];
		for(var i=0,str;str=['a','b'][i++];){
			var t=tool.create();
			t.innerHTML=str;
			ary.push(t);
		}
		//通用的对象池实现
		var objectPoolFactory=function (createObjFn) {
			var objectPool=[];
			return {
				create:function  () {
					var obj=objectPool.length===0?createObjFn.apply(this.arguments):objectPool.shift();
					return obj;
				},
				recover:function  () {
					objectPool.push(obj);
				}
			}
		}

猜你喜欢

转载自blog.csdn.net/Miss_hhl/article/details/103703068