前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript设计模式--享元模式

JavaScript设计模式--享元模式

作者头像
奋飛
修改2020-10-21 09:57:13
3880
修改2020-10-21 09:57:13
举报
文章被收录于专栏:Super 前端Super 前端

一、定义

享元(flyweight)模式是一种用于性能优化的模式,核心是运用共享技术来有效支持大量细刻度的对象。 在JavaScript中,浏览器特别是移动端的浏览器分配的内存并不算多,如何节省内存就成了一个非常有意义的事情。 享元模式是一种用时间换空间的优化模式

内衣工厂有100种男士内衣、100中女士内衣,要求给每种内衣拍照。如果不使用享元模式则需要200个塑料模特;使用享元模式,只需要男女各1个模特。

二、什么场景下使用享元模式?

(1)程序中使用大量的相似对象,造成很大的内存开销 (2)对象的大多数状态都可以变为外部状态,剥离外部状态之后,可以用相对较少的共享对象取代大量对象

三、如何应用享元模式?

第一种是应用在数据层上,主要是应用在内存里大量相似的对象上; 第二种是应用在DOM层上,享元可以用在中央事件管理器上用来避免给父容器里的每个子元素都附加事件句柄。

享元模式要求将对象的属性分为内部状态外部状态

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

享元模式中常出现工厂模式,Flyweight的内部状态是用来共享的,Flyweight factory负责维护一个Flyweight pool(模式池)来存放内部状态的对象。

缺点:对象数量少的情况,可能会增大系统的开销,实现的复杂度较大!

四、示例:文件上传

var Upload = function(uploadType) {
    this.uploadType = uploadType;
}

/* 删除文件(内部状态) */
Upload.prototype.delFile = function(id) {
    uploadManger.setExternalState(id, this);    // 把当前id对应的外部状态都组装到共享对象中
    // 大于3000k提示
    if(this.fileSize < 3000) {
        return this.dom.parentNode.removeChild(this.dom);
    }
    if(window.confirm("确定要删除文件吗?" + this.fileName)) {
        return this.dom.parentNode.removeChild(this.dom);
    }
}

/** 工厂对象实例化 
 *  如果某种内部状态的共享对象已经被创建过,那么直接返回这个对象
 *  否则,创建一个新的对象
 */
var UploadFactory = (function() {
    var createdFlyWeightObjs = {};
    return {
        create: function(uploadType) {
            if(createdFlyWeightObjs[uploadType]) {
                return createdFlyWeightObjs[uploadType];
            }
            return createdFlyWeightObjs[uploadType] = new Upload(uploadType);
        }
    };
})();

/* 管理器封装外部状态 */
var uploadManger = (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];
            }
        }
    };
})();

/*触发上传动作*/
var id = 0;
window.startUpload = function(uploadType, files) {
    for(var i=0,file; file = files[i++];) {
        var uploadObj = uploadManger.add(++id, uploadType, file.fileName, file.fileSize);
    }
};

/* 测试 */
startUpload("plugin", [
    {
        fileName: '1.txt',
        fileSize: 1000
    },{
        fileName: '2.txt',
        fileSize: 3000
    },{
        fileName: '3.txt',
        fileSize: 5000
    }
]);
startUpload("flash", [
    {
        fileName: '4.txt',
        fileSize: 1000
    },{
        fileName: '5.txt',
        fileSize: 3000
    },{
        fileName: '6.txt',
        fileSize: 5000
    }
]);

五、补充:

(1)直接改变形参Demo

function f1() {
    var obj = {a: 1};
    f2(obj);
    console.log(obj);   // {a: 1, b: 2}
}
function f2(obj) {
    obj.b = 2;
}
f1();   

(2)对象池,也是一种性能优化方案,其跟享元模式有一些相似之处,但没有分离内部状态和外部状态的过程。

var objectPoolFactory = function(createObjFn) {
    var objectPool = [];
    return {
        create: function() {
            var obj = objectPool.lenght === 0 ? createObjFn.apply(this, arguments) : objectPool.shift();
            return obj;
        },
        recover: function() {
            objectPool.push(obj);
        }
    };
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年12月20日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、定义
  • 二、什么场景下使用享元模式?
  • 三、如何应用享元模式?
  • 四、示例:文件上传
  • 五、补充:
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档