享元(flyweight)模式是一种用于性能优化的模式。 享元模式的核心是运用共享技术来有效支持大量细粒度的对象。

内部状态和外部状态

享元模式要求把对象属性划分为内部属性和外部属性。(还是把不同的部分抽象出来,能复用就复用)

  1. 内部状态存储于对象内部,且可被共享。
  2. 外部状态不被共享,是变化的。

将外部状态剥离出去后,在使用的时候作为参数传入,来组合成一个完整的可用对象,这是一种用时间换取空间的优化模式。

何时使用

  1. 程序中有大量相似对象,造成了很大的内存开销。
  2. 对象的大多数状态都是外部状态,这意味着使用少量的共享对象(共享对象的个数为共享状态的排列组合)就可以描述所有对象。

    无内部状态

    也就是说只存在一个共享对象。这时候创建共享对象的工厂函数就成为了一个单例工厂。

    无外部状态

    对js来说,没外部状态下,就不需要组合外部状态和共享对象,没有“享”就不能叫享元模式了吧。书中也没有详细解释js中的享元模式,只是拿Java中的一种情况举了个反例。

    对象池

    对象池维护一个装载空闲对象的池子,需要对象的时候不是直接new,而是转从对象池里获取。如果对象池里没有空闲对象,则创建一个新的对象,当取出的对象完成它的职责后,再进入池子等待被下次获取。

简单的说,一个图书馆就是一个对象池,需要的时候借,看完了再还回去。
http连接池和数据库连接池都是对象池。前端开发中,对象池的使用场景大多和dom操作相关。

  1. var toolTipFactory=(function(){
  2. var toolTipPool=[]
  3. return {
  4. create:function(){
  5. if(toolTipPool.length===0){ // 如果对象池里没东西,则创建一个
  6. var div=document.createElement('div')
  7. document.body.appendChild('div')
  8. return div
  9. }else{
  10. return toolTipPool.shift() // 不为空则取出一个
  11. }
  12. },
  13. recover:function(toolTipDom){
  14. return toolTipPool.push(toolTipDom) // 对象池回收
  15. }
  16. }
  17. })() // 为啥都习惯写闭包把某些属性封闭起来呢,直接声明出对象会有this的问题?

对象池和享元模式的思想有点相似,优化点在于避免重复创建dom节点,毕竟dom节点的创建是前端消耗最大的部分。
进一步的抽象,可以把创建对象的过程再次封装,将对象池的逻辑和创建对象具体是啥分离开。
对象池和享元模式的不同之处是它没有分离内部状态和外部状态,感觉是本着节流的思想,用多少创建多少。