zoukankan      html  css  js  c++  java
  • JavaScript设计模式_09_享元模式

    享元模式属于一种性能优化模式。当前端需要创建大量的js对象时,可以考虑使用这种模式进行优化。尤其是移动端,对内存的占用要求比较高,所以,如何节省内存就变成了一件非常有意义的事情。

    /**
     * pre:享元模式:一种性能优化模式
     * 使用共享技术来有效支持大量细粒度的对象
     */
    //--------- 示例1 -----------
    /*
     * 有一家内衣工厂,生产了50种男士内衣和50种女士内衣。为了推销产品,他们决定用塑料模特拍广告进行推广。
     * 正常情况下,需要用50个男模特和50个女模特,分别为他们穿上一款内衣进行拍照。
     * 为了减少创建模特的开销,我们这里使用享元模式,建立1个男模特和1个女模特。
     * 以下是示例程序:
     */
    var model = function(sex) {
        this.sex = sex;
        this.underwear = null;
    };
    model.prototype.setUnderwear = function(underwear) {
        this.underwear = underwear;
    };
    model.prototype.takePhoto = function() {
        console.log("this sex : " + this.sex + ",this underwear : " + this.underwear);
    };
    
    var maleModel = new model("male");
    for(var i = 1; i <= 50; i++) {
        maleModel.setUnderwear("underwear" + i);
        maleModel.takePhoto();
    }
    var femaleModel = new model("female");
    for(var i = 1; i <= 50; i++) {
        femaleModel.setUnderwear("underwear" + i);
        femaleModel.takePhoto();
    }
    
    //---------- 示例2 -------------
    /*
     * 有一个文件上传模块,同时支持多个文件上传,上传方式分为插件、和flash两种方式,并要求上传的文件具有删除功能。
     * 我们为每一个上传文件创建一个upload对象,通过操作这个对象来实现删除的功能。
     * 以下是示例程序:
     */
    var id = 0;
    window.startUpload = function(uploadType, files) {
        for(var i = 0, a; a = files[i++];) {
            var uploadObj = new Upload(uploadType, a.fileName, a.fileSize);
            uploadObj.init(id++);
        }
    };
    var Upload = function(uploadType, fileName, fileSize) {
        this.uploadType = uploadType;
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.dom = null;
    };
    Upload.prototype.init = function(id) {
        var _self = this;
        this.id = id;
        this.dom = document.createElement("div");
        this.dom.innerHTML = "<span>文件名称:" + this.fileName + ",文件大小:" + this.fileSize + "</span>" + "<button class='delFile'>删除</button>";
        this.dom.querySelector(".delFile").onclick = function() {
            _self.delFile();
        };
        document.body.appendChild(this.dom);
    };
    Upload.prototype.delFile = function() {
        if(this.fileSize < 3000) {
            return this.dom.parentNode.removeChild(this.dom);
        }
        if(window.confirm("确定要删除文件" + this.fileName + "?")) {
            return this.dom.parentNode.removeChild(this.dom);
        }
    };
    
    startUpload("plugin", [{
        fileName: "1.txt",
        fileSize: 1000
    }, {
        fileName: "2.html",
        fileSize: 3000
    }, {
        fileName: "3.pdf",
        fileSize: 5000
    }])
    
    startUpload("flash", [{
        fileName: "4.txt",
        fileSize: 1000
    }, {
        fileName: "5.html",
        fileSize: 3000
    }, {
        fileName: "6.pdf",
        fileSize: 5000
    }]);
    
    //------------ 示例3 ----------------
    /**
     * 为了减少对象的创建,我们使用享元模式,对以上代码进行重构。
     * 示例如下:
     */
    var id = 0;
    var Upload = function(uploadType) {
        this.uploadType = uploadType;
    };
    Upload.prototype.delFile = function(id) {
        manager.setExternalState(id, this);
        if(this.fileSize < 3000) {
            return this.dom.parentNode.removeChild(this.dom);
        }
        if(window.confirm("确定要删除文件" + this.fileName + "?")) {
            return this.dom.parentNode.removeChild(this.dom);
        }
    };
    var createUploadFactory = (function() {
        var objCache = {};
        return function(uploadType) {
            if(objCache[uploadType]) {
                return objCache[uploadType];
            }
            return objCache[uploadType] = new Upload(uploadType);
        }
    })();
    var manager = (function() {
        var uploadCache = {};
        var add = function(id, uploadType, fileName, fileSize) {
            var uploadObj = createUploadFactory(uploadType);
            var dom = document.createElement("div");
            dom.innerHTML = "<span>文件名称:" + fileName + ",文件大小:" + fileSize + "</span>" + "<button class='delFile'>删除</button>";
            dom.querySelector(".delFile").onclick = function() {
                uploadObj.delFile(id);
            };
            document.body.appendChild(dom);
            uploadCache[id] = {
                fileName: fileName,
                fileSize: fileSize,
                dom: dom,
                id: id
            };
            return uploadObj;
        };
        var setExternalState = function(id, obj) {
            var uploadObj = uploadCache[id];
            for(var i in uploadObj) {
                obj[i] = uploadObj[i];
            }
        };
        return {
            add: add,
            setExternalState: setExternalState
        }
    })();
    window.startUpload = function(uploadType, files) {
        for(var i = 0, a; a = files[i++];) {
            manager.add(id++, uploadType, a.fileName, a.fileSize);
        }
    }
    
    startUpload("plugin", [{
        fileName: "1.txt",
        fileSize: 1000
    }, {
        fileName: "2.html",
        fileSize: 3000
    }, {
        fileName: "3.pdf",
        fileSize: 5000
    }])
    
    startUpload("flash", [{
        fileName: "4.txt",
        fileSize: 1000
    }, {
        fileName: "5.html",
        fileSize: 3000
    }, {
        fileName: "6.pdf",
        fileSize: 5000
    }]);
    /**
     * 通过以上的例子,我们可以看出,享元模式把对象的属性进行了缓存,当我们真正需要操作对象的时候,再给对象赋值相应的属性,从而达到一种多态,减少对象创建的效果。
    * 另外,需要注意的是,使用享元模式也带来了一些复杂性问题。比如上面的例子中我们需要维护factory和manager这两个对象,在大部分不需要使用享元模式的情况下,这个开销可以避免 * 。一般来说以下情况发生时可以使用享元模式:
    * 1、一个程序中使用了大量相似的对象;
    * 2、由于使用了大量对象,造成了内存开销过大;
    * 3、对象大多数的状态可变为外部状态;
    * 4、剥离出对象的外部状态之后,可以用相对较少的共享对象取代大量对象。
    */
  • 相关阅读:
    经典网络复现(0)多层感知机和lenet
    将自有数据集下yolov训练结果(*.weights) 在进行部署
    DL基础学习计划
    自有数据集上使用keras训练YOLOv3目标检测
    《基于深度学习的图像语义分割方法综述》阅读理解
    Hessian矩阵以及在血管增强中的应用—OpenCV实现
    QML官方例子Calculator初步解析
    human_pose_estimation_demo的再进一步研究(基于OpenPOSE)
    10年图像处理工程师学习图像处理的小结
    human_pose_estimation_demo的进一步研究(基于OpenPOSE)
  • 原文地址:https://www.cnblogs.com/stinchan/p/7054337.html
Copyright © 2011-2022 走看看