为了可以让对象复用,防止大量重复创建对象,导致资源浪费,使用对象池来管理。
对象池具体含义作用,自行百度。
一 对象池A
二 对象池B
三 字符串key和对象key的效率
一 对象池A
/** * 对象池 */ class ObjectPool { /**存储对象池的Object*/ private pool: Object; public constructor() { this.pool = {}; } /** * 获取对象 * @className 对象类名 * @args 构造函数传参 */ public pop(className:string, ...args:any[]): any { if(this.pool[className] == null){ this.pool[className] = []; } var list:Array<any> = this.pool[className]; if(list.length > 0) { return list.pop(); }else{ var clz: any = egret.getDefinitionByName(className); var argsLen: number = args.length; var obj: any; if(argsLen == 0) { obj = new clz(); } else if(argsLen == 1) { obj = new clz(args[0]); } else if(argsLen == 2) { obj = new clz(args[0],args[1]); } else if(argsLen == 3) { obj = new clz(args[0],args[1],args[2]); } else if(argsLen == 4) { obj = new clz(args[0],args[1],args[2],args[3]); } else if(argsLen == 5) { obj = new clz(args[0],args[1],args[2],args[3],args[4]); } obj.className = className; } return obj; } /** * 回收对象 * @obj 需要回收的对象 */ public push(obj: any): void { var className = obj.className; if(this.pool[className] == null){ console.log("回收对象的数组不存在"); return; } this.pool[className].push(obj); } /** * 创建对象(用于将要大量使用前,预先创建,防止使用时大量创建卡顿) * @className 对象类定义 * @num 创建数量 * @args 构造函数传参 */ public create(className:string, num:number, ...args:any[]){ var list = []; for(var i=0;i<num;i++){ list.push(this.pop(className,...args)); } for(i=0;i<num;i++){ this.push(list.pop()); } } /** * 获取对象池对象数量 * @className 对象类定义 * @return 对象数量 */ public getLen(className:string):number{ if(this.pool[className]){ return this.pool[className].length; } return 0; } /** * 清理对象 * @className 对象类定义
* @funName 清理前执行指定函数 */ public clear(className:string, funName:string = null){ if(this.pool[className]){ funName && this.dealFun(className, funName); this.pool[className] = null; delete this.pool[className]; } } /** * 对象池所有对象执行指定函数 * @className 对象类定义 * @funName 函数名 */ public dealFun(className:string , funName:string){ if(this.pool[className]){ var list:Array<any> = this.pool[className]; var len = list.length; for(var i=0;i<len;i++){ list[i][funName] && list[i][funName](); } } } }
对象池简单用法
var pool:ObjectPool = new ObjectPool(); var rect:eui.Rect = pool.pop("eui.Rect"); pool.push(rect);
二 对象池B
class ObjectPool { /**存储对象池的Object*/ private static pool: Object = {}; /**存储对象的数组*/ private list: Array<any>; /**对象类型*/ private className: string; public constructor(className: string) { this.className = className; this.list = []; } /**获取对象*/ public getObject(): any { if(this.list.length > 0) { return this.list.pop(); } var clazz: any = egret.getDefinitionByName(this.className); return new clazz(); } /**回收对象*/ public returnObject(value: any): void { this.list.push(value); } /** * 获取对象池,如果不存在则新建一个 * @param className 对象类名 * @param initNum 初始化对象池数量 */ public static getPool(className: string,initNum: number = 0): ObjectPool { if(!ObjectPool.pool[className]) { ObjectPool.pool[className] = new ObjectPool(className); if(initNum != 0) { var clazz: any = egret.getDefinitionByName(className); var pool: ObjectPool = ObjectPool.pool[className]; for(var i: number = 0;i < initNum;i++) { pool.returnObject(new clazz()); } } } return ObjectPool.pool[className]; } }
var pool:ObjectPool = ObjectPool.getPool("eui.Rect",10); var rect:eui.Rect = pool.getObject(); pool.returnObject(rect);
B里偷懒没写销毁和统一执行函数等方法,抛除这些, A和B其实差不多。
获取一个对象
A: pool.pop("eui.Rect");
B: pool.getPool("eui.Rect").getObject();
回收一个对象
A:pool.push(obj);
B:pool.getPool("eui.Rect").returnObject();
看似B比较复杂。
但是B可以将pool获取出来,保存这个引用,之后只需要get和return就行了,不需要再传className了。
var pool:ObjectPool = ObjectPool.getPool("eui.Rect");
pool.getObject();
pool.returnObject();
三 字符串key和对象key的效率
对象池可以不传className,而是直接传class(ts里对象貌似是Function),对比如下:
ObjectPool.getPool("eui.Rect");
ObjectPool.getPool(eui.Rect);
创建对象对比
getPool(className:string){ var clazz: any = egret.getDefinitionByName(className); } getPool(clz){ var clazz:any = new clz(); }
传class比传className方便。一个不用怕拼错,一个ctrl+左键就可以定位到这个类。
但是效率要差一点。
使用字符串和对象作为key值的效率对比。
循环100次:0,0
循环1000次:0,3
循环1万次:0,25
循环10万次:1,240
var obj:Object = {};
obj["a"] = 1;
var time = egret.getTimer();
for(var i=0;i<1000;i++){
var b = obj["a"];
}
console.log(egret.getTimer() - time); //0
var obj2:Object = {};
obj2[<any>eui.Rect] = 1;
var time = egret.getTimer();
for(var i = 0;i < 1000;i++) {
var b = obj2[<any>eui.Rect];
}
console.log(egret.getTimer() - time); //3