【D1n910】第15章 享元模式 —— 城市公交车《JavaScript 设计模式》
正常操作,正常分析,大家好,我是D1n910。
今天继续来学习 《JavaScript 设计模式》的第三篇 结构型设计模式
这是一个连续的读书笔记,所以如果你之前的内容没有看的话,可以去看看。
下面是第十章的展览,里面其实链接好了所有1~10的专栏内容,所以直接戳下面的专栏链接就可以快速到达啦。

其他后续章节



这里再次感谢 《Javascript 设计模式》及其作者 张荣铭,专栏内容是在它的基础上生成的。
现在会觉得很多设计模式离我们有点遥远,是因为我们现在都在用大佬写好的框架吧,很多设计模式都包含在框架里了

第三篇 结构型设计模式(P103)
结构型设计模式关注于如何将类或者对象组合成更大、更复杂的结构,以简化设计。
第 15 章 城市公交车 —— 享元模式(P104)
享元模式(Flyweight):运用共享技术有效地支持大量地细粒度的对象,避免对象拥有相同内容造成多余的开销。
这个经常用在大型应用当中。
但是我自己是没看出这个享元模式和之前的桥接模式有什么太大的区别 🤔
可能桥接模式更简单一些。
15.1、翻页需求(P103)
小新在做翻页的需求,他发现自己的内容在 Chrome 浏览器下运行良好,但是到了低版本 IE 浏览器下有卡顿问题。
他的代码如下。
// 模拟 article 数据
var article = [];
var articleIndex = 0;
for (; articleIndex < 10000; articleIndex++) {
article.push('新闻标题' + articleIndex)
}
var dom = null, // 缓存创建的新闻标题元素
paper = 0, // 当前页数
num = 5, // 每页显示新闻树木
i = 0, // 创建新闻元素时保持变量
len = article.length; // 新闻数据长度
// 初始化页面
for (; i < len; i++) {
dom = document.createElement('div');
dom.innerHTML = article[i]; // 默认展示第一页的内容
if (i >= num) {
dom.style.display = 'none'; // 超出第一页新闻英藏
}
document.getElementById('container').appendChild(dom);
}
// 下一页绑定数据
document.getElementById('next_page').onclick = function () {
var div = document.getElementById('container').getElementsByTagName('div'),
// 获取所有新闻标题包装元素
j = k = n = 0; // j, k 循环变量,n 当前页显示的第一个新闻序号
n = ++paper % Math.ceil(len / num) * num; // 获取当前页显示的第一个新闻序号
for (; j < len; j++) {
div[j].style.display = 'none'; // 隐藏所有新闻
}
for (; k < 5; k++) {
if (div[n + k]) {
div[n + k].style.display = 'block'; // 显示当前页新闻
}
}
}
15.2、冗余结构(P104)
上面所有的新闻都有同样的结构,只是元素不一样。而且每次点下一页,都会直接操作海量的数据,这样的内存开销在低版本的 IE 上当然就严重影响其性能了。
可以用享元模式将相同的数据、方法共享分离。数据、方法分为内部数据、内部方法和外部数据、外部方法。提取出相似或者共有的数据部分以后,可以减少开销,提高性能。
15.3、享元对象(P104)
新闻个体都是有相同的结构,提取出相似的结构以后,我们可以提供一个操作方法来使用内部数据。
var flyWeight = function () {
// 已创建的元素
var created = [];
// 创建一个新闻包装元素
function create() {
var div = document.createElement('div');
document.getElementById('container').appendChild(div);
created.push(div);
return div;
}
return {
getDiv() {
if (created.length < 5) {
return create();
} else {
var div = created.shift();
created.push(div);
return div;
}
}
}
}()
通过上面的方法,我们可以实现由原来的操作所有的数据变成只是操作页面上展示出来的五个数据。
15.4、实现需求(P106)
根据上面的享元对象,把原来的代码中外部代码部分改造一下:
var paper = 0, // 当前页数
num = 5, // 每页显示新闻数目
i = 0, // 创建新闻元素时保持变量
len = article.length; // 新闻数据长度
// 初始化页面
for (; i < num; i++) {
flyWeight.getDiv().innerHTML = article[i] || ''
}
// 下一页绑定事件
document.getElementById('next_page').onclick = function() {
// 获取所有新闻标题包装元素
var j = k = n = 0; // j, k 循环变量,n 当前页显示的第一个新闻序号
n = ++paper * num % len; // 获取当前页显示的第一个新闻序号
console.log('n', n, 'paper', paper)
for (; k < num; k++) {
flyWeight.getDiv().innerHTML = article[n + k] || article[n + k - len] || ''
}
}
忆之获
享元模式应用目的是为了提高程序的执行效率与系统性能。因此在大型系统开发中应用是比较广泛的。
如果程序比较小,性能与内存的消耗对程序的执行影响不大时,强行应用享元模式而引入复杂的代码逻辑,反而会收到负效应。
本章 End
加油加油
2021年02月23日 D1n910 学习于南山后海