Egret中的对象池ObjectPool

为了可以让对象复用,防止大量重复创建对象,导致资源浪费,使用对象池来管理。

对象池具体含义作用,自行百度。

 

一 对象池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

 

 

转载于:https://www.cnblogs.com/gamedaybyday/p/6083164.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值