享元(flyweight)模式是一种用于性能优化的模式。 享元模式的核心是运用共享技术来有效支持大量细粒度的对象。
内部状态和外部状态
享元模式要求把对象属性划分为内部属性和外部属性。(还是把不同的部分抽象出来,能复用就复用)
- 内部状态存储于对象内部,且可被共享。
- 外部状态不被共享,是变化的。
将外部状态剥离出去后,在使用的时候作为参数传入,来组合成一个完整的可用对象,这是一种用时间换取空间的优化模式。
何时使用
- 程序中有大量相似对象,造成了很大的内存开销。
- 对象的大多数状态都是外部状态,这意味着使用少量的共享对象(共享对象的个数为共享状态的排列组合)就可以描述所有对象。
无内部状态
也就是说只存在一个共享对象。这时候创建共享对象的工厂函数就成为了一个单例工厂。无外部状态
对js来说,没外部状态下,就不需要组合外部状态和共享对象,没有“享”就不能叫享元模式了吧。书中也没有详细解释js中的享元模式,只是拿Java中的一种情况举了个反例。对象池
对象池维护一个装载空闲对象的池子,需要对象的时候不是直接new,而是转从对象池里获取。如果对象池里没有空闲对象,则创建一个新的对象,当取出的对象完成它的职责后,再进入池子等待被下次获取。
简单的说,一个图书馆就是一个对象池,需要的时候借,看完了再还回去。
http连接池和数据库连接池都是对象池。前端开发中,对象池的使用场景大多和dom操作相关。
var toolTipFactory=(function(){
var toolTipPool=[]
return {
create:function(){
if(toolTipPool.length===0){ // 如果对象池里没东西,则创建一个
var div=document.createElement('div')
document.body.appendChild('div')
return div
}else{
return toolTipPool.shift() // 不为空则取出一个
}
},
recover:function(toolTipDom){
return toolTipPool.push(toolTipDom) // 对象池回收
}
}
})() // 为啥都习惯写闭包把某些属性封闭起来呢,直接声明出对象会有this的问题?
对象池和享元模式的思想有点相似,优化点在于避免重复创建dom节点,毕竟dom节点的创建是前端消耗最大的部分。
进一步的抽象,可以把创建对象的过程再次封装,将对象池的逻辑和创建对象具体是啥分离开。
对象池和享元模式的不同之处是它没有分离内部状态和外部状态,感觉是本着节流的思想,用多少创建多少。