享元模式
享元(flyweight)模式是一种用于性能优化的模式,“fly”在这里是苍蝇的意思,意为蝇量级。享元模式的核心是运用共享技术来有效支持大量细粒度的对象。
享元模式的核心思想就是共享对象,借此达到节省性能的目的。比如说有100套不同的衣服需要拍照,正常的想法都是请一个模特让他换100套衣服即可,但我们实际上常常干类似于请100个模特这样的事情,这对于性能的消耗其实是大的。而只请一个模特,那个唯一的模特就是共享的对象。
享元模式要求将对象的属性划分为内部状态与外部状态(状态在这里通常指属性)。什么意思呢?比如上面的例子,不变的是他的性别和模特属性,变的就是具体的衣服。所以内部状态就是指储存在对象内部的可以被共享且不变的属性或方法。而外部状态则是根据具体场景而变化的,且无法共享的属性或方法。也就是说要抽离可共享的和不可共享的。
什么情况下应该使用享元模式?
- 一个程序中使用了大量的相似对象。
- 由于使用了大量对象,造成很大的内存开销。
- 对象的大多数状态都可以变为外部状态。
- 剥离出对象的外部状态之后,可以用相对较少的共享对象取代大量对象。
模特的例子如下:
var people=function(sex){
this.sex=sex;
}
models=(function(){
var model={}; //储存共享的对象
return{
create:function( sex ){
if( model[sex] ){ //存在对应对象就返回
return model[sex];
}else{ //不存在就创建
return model[sex]=new people(sex);
}
}
}
})(); for(var i=0;i<100;i++){
var male=models.create( male );
male.takephoto(); //这里没有具体实现,只是做个例子
}
对象池
对象池维护一个装载空闲对象的池子,如果需要对象的时候,不是直接new,而是转从对象池里获取。如果对象池里没有空闲对象,则创建一个新的对象,当获取出的对象完成它的职责之后, 再进入池子等待被下次获取。
handler=(function(){
var chizi=[];
return {
getone:function(){
if( chizi.length==0 ){ //池子空了
var div = document.createElement( 'div' ); // 创建一个dom,这里只是一个例子
document.body.appendChild( div );
return div;
}else{ //池子没空
return chizi.shift();
}
},
recover:function( obj ){
return chizi.push( obj );
}
}
})();
对象池是另外一种性能优化方案,它跟享元模式有一些相似之处,但没有分离内部状态和外部状态这个过程。