美文网首页
享元模式

享元模式

作者: bby365 | 来源:发表于2018-07-05 09:55 被阅读0次

    减少对象的数量,将对象属性划分为内部状态和外部状态。
    内衣广告拍摄例子,将100个对象变成2个对象。

    // 每次都创建一个对象
    for ( var i = 1; i <= 50; i++ ){
            var maleModel = new Model( 'male', 'underwear' + i );
            maleModel.takePhoto();
    };
    // 只创建一个对象,再给对象添加一个变化的属性
    for ( var i = 1; i <= 50; i++ ){
            maleModel.underwear = 'underwear' + i;
            maleModel.takePhoto();
    };
    
    • 文件上传
    1. 普通方法
    window.startUpload = function( uploadType, files ){ 
        for ( var i = 0, file; file = files[ i++ ]; ){
            // 每次都会创建一个新对象
            var uploadObj = new Upload( uploadType, file.fileName, file.fileSize );
            uploadObj.init( id++ ); // 给upload 对象设置一个唯一的id
        }
    };
    
    1. 享元模式重构
      uploadType划为内部状态,文件相关信息抽离为外部状态。
      2.1 定义Upload
    // 1. 不会直接调用Upload
    var Upload = function( uploadType){
            this.uploadType = uploadType;
    };
    
    // 2. 使用工厂实例化,这样每种类型只会创建一个对象
    var UploadFactory = (function(){
            var createdFlyWeightObjs = {};
            return {
                create: function( uploadType){
                    if ( createdFlyWeightObjs [ uploadType] ){
                        return createdFlyWeightObjs [ uploadType];
                    }
                    return createdFlyWeightObjs [ uploadType] = new Upload( uploadType);
                }
            }
    })();
    

    2.2 外部状态管理器
    只有需要时,才调用管理器方法

    var uploadManager = (function(){
        var uploadDatabase = {};
        return {
            add: function( id, uploadType, fileName, fileSize ){
                var flyWeightObj = UploadFactory.create( uploadType );
                // 处理逻辑...
    
                // 将外部信息保存
                uploadDatabase[ id ] = {
                    fileName: fileName,
                    fileSize: fileSize,
                    dom: dom
                };
                
                return flyWeightObj ;
            },
            // 获取外部状态信息
            setExternalState: function( id, obj ){
                var uploadData = uploadDatabase[ id ];
                for ( var i in uploadData ){
                    obj[ i ] = uploadData[ i ];
                }
            }
        }
    })();
    

    2.3 上传函数

    var id = 0;
    window.startUpload = function( uploadType, files ){
        for ( var i = 0, file; file = files[ i++ ]; ){
            // 不是直接调用构造函数,使用的是外部管理器方法
            var uploadObj = uploadManager.add( ++id, uploadType, file.fileName, file.fileSize );
        }
    };
    

    • 对象池
      需要用一个对象时,不是直接new 一个对象,先去对象池里拿,用完后再放回对象池。如果,对象池没有了对象,就再创建一个。
      使用场景:避免频繁创建和删除DOM节点。
      对象池:一般有创建对象和回收对象俩个方法。
    var toolTipFactory = (function(){
        var toolTipPool = []; // toolTip 对象池
        return {
            create: function(){
                if ( toolTipPool.length === 0 ){ 
                    var div = document.createElement( 'div' ); 
                    document.body.appendChild( div );
                    recovereturn div;
                }else{ 
                    return toolTipPool.shift(); 
                }
            },
            recover: function( tooltipDom ){
                return toolTipPool.push( tooltipDom ); 
            }
        }
    })();
    
    1. 如果使用中并没有主动调用回收方法,
    那么对象池中就不会存储之前创建的对象
    

    集中使用方法:

    var ary = [];
    for ( var i = 0, str; str = [ 'A', 'B' ][ i++ ]; ){
        var toolTip = toolTipFactory.create();
        toolTip.id = str // 便于辨别是否为对象池中对象
        toolTip.innerHTML = str;
        ary.push( toolTip );
    };
    // 没有回收对象,后面将创建6个对象,而不是4个
    for ( var i = 0, toolTip; toolTip = ary[ i++ ]; ){
        toolTipFactory.recover( toolTip );
    };
    
    for ( var i = 0, str; str = [ 'A', 'B', 'C', 'D', 'E', 'F' ][ i++ ]; ){
        var toolTip = toolTipFactory.create();
        toolTip.innerHTML = str;
    };
    

    如果把具体的创建过程封装起来,就会实现通用对象池。

    // createObjFn 是具体的创建对象函数,又外部传入
    var objectPoolFactory = function( createObjFn ){
        var objectPool = [];
        return {
            create: function(){
                var obj = objectPool.length === 0 ?
                createObjFn.apply( this, arguments ) : objectPool.shift();
                return obj;
            },
            recover: function( obj ){
                objectPool.push( obj );
    
            }
        }
    };
    

    相关文章

      网友评论

          本文标题:享元模式

          本文链接:https://www.haomeiwen.com/subject/xxvuuftx.html