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

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元素数据达到了最小化。这便是对程序性能的提升。

《JavaScript设计模式 | 15-享元模式》 图例

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

    原文作者:weixin_33697898
    原文地址: https://blog.csdn.net/weixin_33697898/article/details/88517106
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞