Skip to content

9、享元模式

案例

  • 500模特

性能优化模式

  • 蝇量级
  • 运用共享技术来有效支持大量细粒度的对象

内部状态 外部状态

目标:运用共享技术来有效支持大量细粒度的对象

划分:

  • 内部状态存储于对象内部。
  • 内部状态可以被一些对象共享。
  • 内部状态独立于具体的场景,通常不会改变。
  • 外部状态取决于具体的场景,并根据场景而变化,外部状态不能被共享。

想要实现享元模式,解决两个问题:

1、对象工厂:只有当某种共享对象被真正需要时,它才从工厂中被创建出来;

js
    var UploadFactory = (function(){
        var createdFlyWeightObjs = {};
        return {
            create: function( uploadType){
                if ( createdFlyWeightObjs [ uploadType] ){
                    return createdFlyWeightObjs [ uploadType];
                }
                return createdFlyWeightObjs [ uploadType] = new Upload( uploadType);
            }
        }
    })();

2、管理器来记录:外部状态通过某个钩子和共享对象联系起来;

js
    var uploadManager = (function(){
        var uploadDatabase = {};
        return {
            add: function( id, uploadType, fileName, fileSize ){
                var flyWeightObj = UploadFactory.create( uploadType );

                var dom = document.createElement( 'div' );
                dom.innerHTML =
                        '<span>文件名称:'+ fileName +',文件大小: '+ fileSize +'</span>' +
                        '<button class="delFile">删除</button>';
                dom.querySelector( '.delFile' ).onclick = function(){
                    flyWeightObj.delFile( id );
                }
                document.body.appendChild( dom );
                uploadDatabase[ id ] = {
                    fileName: fileName,
                    fileSize: fileSize,
                    dom: dom
                };
                return flyWeightObj ;
            },
            setExternalState: function( id, flyWeightObj ){
                var uploadData = uploadDatabase[ id ];
                for ( var i in uploadData ){
                    flyWeightObj[ i ] = uploadData[ i ];
                }
            }
        }
    })();

何时使用

  • 一个程序中使用了大量的相似对象。
  • 由于使用了大量对象,造成很大的内存开销。
  • 对象的大多数状态都可以变为外部状态。
  • 剥离出对象的外部状态之后,可以用相对较少的共享对象取代大量对象

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