美文网首页
JavaScript设计模式 | 15-享元模式

JavaScript设计模式 | 15-享元模式

作者: 夏海峰 | 来源:发表于2019-02-27 21:22 被阅读32次

    1、模式定义

    享元模式,运用共享技术,有效地支持大量的细粒度的对象,以避免对象之间拥有相同内容而造成多余的性能开销。

    享元模式,可以解决冗余结构对程序性能造成严重影响的问题。所谓享元模式,主要是对数据、方法的共享进行分离。它把数据和方法划分成内部数据、外部数据、内部方法和外部方法。内部数据和内部方法是相似的或者共有的,把内部数据和内部方法提取出来,进而减少性能开销。

    2、生活中的享元模式

    比如100个人从同一个起点出去,去往同一个目的地。如果这100个人都独自开车去,则每个人需要花费100元。但是,如果这100个人选择乘坐一辆巴士去,则每个人只需花费5元。这其中就蕴含着享元模式的设计思想。

    3、享元模式 举例

    现有一个新闻列表的页面,每页显示5条新闻。当点击页面中的“下一页”时,即实现新闻列表的翻页功能。在这个需求中,我们知道,每次翻页,页面结构中变化的只是新闻元素(如新闻标题、时间、图片等),但新闻的容器盒子是没有变化的。

    下面示例中,我们就使用享元模式的思想来实现,即每次翻页时,我们不重新创建新闻的容器,而只重新创建新闻列表中发生了变化的元素。这样即可提升程序的性能。

    // 享元模式
    var FlyWeight = function() {
        // 已创建的元素
        var created = [];
        // 创建一个新闻容器
        function create() {
            var dom = document.createElement('div'); // 一条新闻的容器
            document.getElementById('page').appendChild(dom);
            // 缓存新创建的元素
            created.push(dom);
            return dom;
        }
        return {
            // 获取新闻元素
            getDiv: function() {
                // 每页显示5条新闻
                if (created.length < 5) {
                    return create();
                } else {
                    // 获取第一个元素,并插入至最后
                    var div = created.shift();
                    created.push(div);
                    return div;
                }
            }
        }
    }();
    
    // 使用上述封装的享元模式,实现需求
    var page = 0, num = 5, len = article.length;
    // 添加5条新闻
    for (var i = 0; i<5; i++) {
        if (article[i]) {
            // 只更新内容,不重新创建容器
            FlyWeight.getDiv().innerHTML = article[i];
        }
    }
    // 给“下一页”按钮绑定翻页事件
    document.getElementById('next-page').onclick = function() {
        if (article.length < 5) {
            return;
        }
        // 获取当前页的第一条新闻索引
        var n = ++page * num % len;
        // 插入5条新闻
        for (var j = 0; j<5; j++) {
            if (article[n+j]) {
                FlyWeight.getDiv().innerHTML = article[n+j];
            } else if (article[n+j-len]) {
                FlyWeight.getDiv().innerHTML = article[n+j-len];
            } else {
                FlyWeight.getDiv().innerHTML = "";
            }
        }
    }
    

    使用享元模式对页面进行优化后,每次翻页所需要操作并更新的DOM元素数据达到了最小化。这便是对程序性能的提升。

    图例

    4、享元模式 再举例

    var FlyWeight = {
        moveX: function(x) {
            this.x = x;
        },
        moveY: function(y) {
            this.y = y;
        }
    }
    
    var Player = function(x, y, color) {
        this.x = x;
        this.y = y;
        this.color = color;
    }
    Player.prototype = FlyWeight;
    Player.prototype.changeColor = function(color) {
        this.color = color;
    }
    
    // 让精灵继承移动的方法
    var Spirit = function(x, y, r) {
        this.x = x;
        this.y = y;
        this.r = r;
    }
    Spirit.prototype = FlyWeight;
    Spirit.prototype.changeR = function(r) {
        this.r = r;
    }
    

    像这样把子类中相似的数据或方法提取出来,以减少子类重写时造成的额外开销。这也是享元模式的设计思想。

    5、小结

    享元模式把共有的数据和方法提取出来,目的是为了提高程序的执行效率,进一步提升系统的性能。享元模式有助于减少内存消耗,在大型系统开发中应用非常广泛。当然在一些小型的程序中,性能和内存的消耗对程序执行的影响不大时,如果强行使用享元模式则会导致代码逻辑变得复杂,往往会收到负效应。


    本章结束 2019-02-27

    相关文章

      网友评论

          本文标题:JavaScript设计模式 | 15-享元模式

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