今天看了一位叫飞叶的老师的视频,学习到了池化技术这一概念。对象池模式也是一种比较常见的设计模式了,通俗来说池化技术是为了提高应用性能和减少开销。比如公共食堂有取筷子的地方,那么放筷子的容器属于一个对象池,专门存放筷子这个"对象",每次人们需要用筷子的时候就在筷子盒里面拿,用完又放回去筷子盒(对象池),当食堂就餐人数较多时,筷子被拿完了,筷子盒现在空了,那么就需要买一些新的筷子(即创建新的对象)供人们使用,所有新的和旧的筷子被使用完后又放回筷子盒。所以说对象池集中管理一些具有相同规则的同质对象,它们是具有相同的逻辑状态的,比如所有筷子都是有相同的功能,而不能把餐盘这种“对象”和筷子放在一起。
一般对象池技术应用场景有连接池、内存池等等。连接池一般多见于JDBC、Redis连接池、http连接池等等。那么前端对象池技术的应用核心也是为对象复用,比如React也使用到了对象重用池的优化策略和cocos引擎 Cocos Creator 使用对象池
比如一些小游戏类似消灭星星,那么这些星星需要被反复多次的生成和消除,频繁地生成和销毁节点需要消耗大量性能,所以采用对象池技术把消除的星星存起来,需要生成时再从池子中拿即可。
小例子
先返回一个星星工厂对象,它里面有一个星星对象池,一个创建星星对象方法,一个回收星星对象方法。
var starFactory = (function(){
// 星星对象池
var starPool = [];
return {
createStar(){
// 当星星对象池为空时,创建新的星星并返回
if(!starPool.length){
// 用一个div节点比作星星节点
const starDom = document.createElement('div');
document.body.appendChild(starDom);
return starDom;
}else{
// 当星星对象池不为空,直接用池子里的节点
starPool.pop();
}
},
// 回收对象到对象池
recoverStar(starDom){
return starPool.push(starDom);
}
}
})()
游戏开始,首批星星节点先被创建并初始化,并且收集新的节点。
var divArr = [];
var starArr = ['黄色星星', '蓝色星星'];
for(let i=0;i<starArr.length;i++){
// 创建新节点
let starDiv = starFactory.createStar();
// 并初始化节点
starDiv.innerHTML = starArr[i];
// 收集新节点
divArr.push(starDiv);
}
当部分星星节点被消除时,又需要产生一些新的星星节点,此时把收集的新节点回收到对象池,这时可以先再池子拿对象,等对象池为空时再创建新节点,同时再收集它们。
for(let i=0;i<divArr.length;i++){
// 先把上一次收集的新节点全部回收到池子
starFactory.recoverStar(divArr[i]);
}
var starArr2 = ['绿色星星', '紫色星星', '红色星星'];
for(let i=0;i<starArr2.length;i++){
// 这次创建节点时,因为上一次有两个节点被回收了,
// 所以部分可以直接在池子拿不需要create元素,部分需要新创建
let starDiv = starFactory.createStar();
starDiv.innerHTML = starArr[i];
// 再次收集新创建的节点
divArr.push(starDiv)
}
上述每一次都是先把上一次收集的结果回收一下,再用工厂对象给创建出来,那么可以提取出代码块
var divArr = [];
var SAR = () => {
for(let i=0;i<divArr.length;i++){
starFactory.recoverStar(divArr[i]);
}
var starArr2 = resArr; //接口返回的数据
for(let i=0;i<starArr2.length;i++){
let starDiv = starFactory.createStar();
starDiv.innerHTML = starArr[i];
divArr.push(starDiv)
}
}