【D1n910】第15章 享元模式 —— 城市公交車《JavaScript 設(shè)計(jì)模式》
正常操作,正常分析,大家好,我是D1n910。
今天繼續(xù)來學(xué)習(xí) 《JavaScript 設(shè)計(jì)模式》的第三篇 結(jié)構(gòu)型設(shè)計(jì)模式
這是一個(gè)連續(xù)的讀書筆記,所以如果你之前的內(nèi)容沒有看的話,可以去看看。
下面是第十章的展覽,里面其實(shí)鏈接好了所有1~10的專欄內(nèi)容,所以直接戳下面的專欄鏈接就可以快速到達(dá)啦。

其他后續(xù)章節(jié)



這里再次感謝 《Javascript 設(shè)計(jì)模式》及其作者 張榮銘,專欄內(nèi)容是在它的基礎(chǔ)上生成的。
現(xiàn)在會(huì)覺得很多設(shè)計(jì)模式離我們有點(diǎn)遙遠(yuǎn),是因?yàn)槲覀儸F(xiàn)在都在用大佬寫好的框架吧,很多設(shè)計(jì)模式都包含在框架里了

第三篇 結(jié)構(gòu)型設(shè)計(jì)模式(P103)
結(jié)構(gòu)型設(shè)計(jì)模式關(guān)注于如何將類或者對(duì)象組合成更大、更復(fù)雜的結(jié)構(gòu),以簡(jiǎn)化設(shè)計(jì)。
第 15?章 城市公交車 —— 享元模式(P104)
享元模式(Flyweight):運(yùn)用共享技術(shù)有效地支持大量地細(xì)粒度的對(duì)象,避免對(duì)象擁有相同內(nèi)容造成多余的開銷。
這個(gè)經(jīng)常用在大型應(yīng)用當(dāng)中。
但是我自己是沒看出這個(gè)享元模式和之前的橋接模式有什么太大的區(qū)別 ??
可能橋接模式更簡(jiǎn)單一些。
15.1、翻頁需求(P103)
小新在做翻頁的需求,他發(fā)現(xiàn)自己的內(nèi)容在 Chrome 瀏覽器下運(yùn)行良好,但是到了低版本 IE 瀏覽器下有卡頓問題。
他的代碼如下。
// 模擬 article 數(shù)據(jù)
var article = [];
var articleIndex = 0;
for (; articleIndex < 10000; articleIndex++) {
? ?article.push('新聞標(biāo)題' + articleIndex)
}
var dom = null, // 緩存創(chuàng)建的新聞標(biāo)題元素
paper = 0, // 當(dāng)前頁數(shù)
num = 5, // 每頁顯示新聞樹木
i = 0, // 創(chuàng)建新聞元素時(shí)保持變量
len = article.length; // 新聞數(shù)據(jù)長(zhǎng)度
// 初始化頁面
for (; i < len; i++) {
? ?dom = document.createElement('div');
? ?dom.innerHTML ?= article[i]; // 默認(rèn)展示第一頁的內(nèi)容
? ?if (i >= num) {
? ? ? ?dom.style.display = 'none'; // 超出第一頁新聞?dòng)⒉?/p>
? ?}
? ?document.getElementById('container').appendChild(dom);
}
// 下一頁綁定數(shù)據(jù)
document.getElementById('next_page').onclick = function () {
? ?var div = document.getElementById('container').getElementsByTagName('div'),
? ?// 獲取所有新聞標(biāo)題包裝元素
? ?j = k = n = 0; // j, k 循環(huán)變量,n 當(dāng)前頁顯示的第一個(gè)新聞序號(hào)
? ?n = ++paper % Math.ceil(len / num) * num; // 獲取當(dāng)前頁顯示的第一個(gè)新聞序號(hào)
? ?for (; j < len; j++) {
? ? ? ?div[j].style.display = 'none'; // 隱藏所有新聞
? ?}
? ?for (; k < 5; k++) {
? ? ? ?if (div[n + k]) {
? ? ? ? ? ?div[n + k].style.display = 'block'; // 顯示當(dāng)前頁新聞
? ? ? ?}
? ?}
}
15.2、冗余結(jié)構(gòu)(P104)
上面所有的新聞都有同樣的結(jié)構(gòu),只是元素不一樣。而且每次點(diǎn)下一頁,都會(huì)直接操作海量的數(shù)據(jù),這樣的內(nèi)存開銷在低版本的 IE 上當(dāng)然就嚴(yán)重影響其性能了。
可以用享元模式將相同的數(shù)據(jù)、方法共享分離。數(shù)據(jù)、方法分為內(nèi)部數(shù)據(jù)、內(nèi)部方法和外部數(shù)據(jù)、外部方法。提取出相似或者共有的數(shù)據(jù)部分以后,可以減少開銷,提高性能。
15.3、享元對(duì)象(P104)
新聞個(gè)體都是有相同的結(jié)構(gòu),提取出相似的結(jié)構(gòu)以后,我們可以提供一個(gè)操作方法來使用內(nèi)部數(shù)據(jù)。
var flyWeight = function () {
? ?// 已創(chuàng)建的元素
? ?var created = [];
? ?// 創(chuàng)建一個(gè)新聞包裝元素
? ?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;
? ? ? ? ? ?}
? ? ? ?}
? ?}
}()
通過上面的方法,我們可以實(shí)現(xiàn)由原來的操作所有的數(shù)據(jù)變成只是操作頁面上展示出來的五個(gè)數(shù)據(jù)。
15.4、實(shí)現(xiàn)需求(P106)
根據(jù)上面的享元對(duì)象,把原來的代碼中外部代碼部分改造一下:
var paper = 0, // 當(dāng)前頁數(shù)
num = 5, // 每頁顯示新聞數(shù)目
i = 0, // 創(chuàng)建新聞元素時(shí)保持變量
len = article.length; // 新聞數(shù)據(jù)長(zhǎng)度
// 初始化頁面
for (; i < num; i++) {
? ?flyWeight.getDiv().innerHTML = article[i] || ''
}
// 下一頁綁定事件
document.getElementById('next_page').onclick = function() {
? ?// 獲取所有新聞標(biāo)題包裝元素
? ?var j = k = n = 0; // j, k 循環(huán)變量,n 當(dāng)前頁顯示的第一個(gè)新聞序號(hào)
? ?n = ++paper * num % len; // 獲取當(dāng)前頁顯示的第一個(gè)新聞序號(hào)
? ?console.log('n', n, 'paper', paper)
? ?for (; k < num; k++) {
? ? ? ?flyWeight.getDiv().innerHTML = article[n + k] || article[n + k - len] || ''
? ?}
}
?
憶之獲
享元模式應(yīng)用目的是為了提高程序的執(zhí)行效率與系統(tǒng)性能。因此在大型系統(tǒng)開發(fā)中應(yīng)用是比較廣泛的。
如果程序比較小,性能與內(nèi)存的消耗對(duì)程序的執(zhí)行影響不大時(shí),強(qiáng)行應(yīng)用享元模式而引入復(fù)雜的代碼邏輯,反而會(huì)收到負(fù)效應(yīng)。
本章 End
加油加油
2021年02月23日 D1n910 學(xué)習(xí)于南山后海