摘要:作者按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用和兩種語(yǔ)言實(shí)現(xiàn)。享元模式提醒我們將一個(gè)對(duì)象的屬性劃分為內(nèi)部和外部狀態(tài)。
作者按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript和python兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)現(xiàn)方式,但此小冊(cè)只記錄最直截了當(dāng)?shù)膶?shí)現(xiàn)方式 :)
個(gè)人技術(shù)博客-godbmw.com 歡迎來(lái)玩! 每周至少 1 篇原創(chuàng)技術(shù)分享,還有開(kāi)源教程(webpack、設(shè)計(jì)模式)、面試刷題(偏前端)、知識(shí)整理(每周零碎),歡迎長(zhǎng)期關(guān)注!本篇博客地址是:《每天一個(gè)設(shè)計(jì)模式之享元模式》。
如果您也想進(jìn)行知識(shí)整理 + 搭建功能完善/設(shè)計(jì)簡(jiǎn)約/快速啟動(dòng)的個(gè)人博客,請(qǐng)直接戳theme-bmw
0. 項(xiàng)目地址享元模式·代碼
《每天一個(gè)設(shè)計(jì)模式》地址
1. 什么是“享元模式”?享元模式:運(yùn)用共享技術(shù)來(lái)減少創(chuàng)建對(duì)象的數(shù)量,從而減少內(nèi)存占用、提高性能。
享元模式提醒我們將一個(gè)對(duì)象的屬性劃分為內(nèi)部和外部狀態(tài)。
內(nèi)部狀態(tài):可以被對(duì)象集合共享,通常不會(huì)改變
外部狀態(tài):根據(jù)應(yīng)用場(chǎng)景經(jīng)常改變
享元模式是利用時(shí)間換取空間的優(yōu)化模式。
2. 應(yīng)用場(chǎng)景享元模式雖然名字聽(tīng)起來(lái)比較高深,但是實(shí)際使用非常容易:只要是需要大量創(chuàng)建重復(fù)的類的代碼塊,均可以使用享元模式抽離內(nèi)部/外部狀態(tài),減少重復(fù)類的創(chuàng)建。
為了顯示它的強(qiáng)大,下面的代碼是簡(jiǎn)單地實(shí)現(xiàn)了大家耳熟能詳?shù)摹皩?duì)象池”,以彰顯這種設(shè)計(jì)模式的魅力。
3. 代碼實(shí)現(xiàn)這里利用python和javascript實(shí)現(xiàn)了一個(gè)“通用對(duì)象池”類--ObjectPool。這個(gè)類管理一個(gè)裝載空閑對(duì)象的數(shù)組,如果外部需要一個(gè)對(duì)象,直接從對(duì)象池中獲取,而不是通過(guò)new操作。
對(duì)象池可以大量減少重復(fù)創(chuàng)建相同的對(duì)象,從而節(jié)省了系統(tǒng)內(nèi)存,提高運(yùn)行效率。
為了形象說(shuō)明“享元模式”在“對(duì)象池”實(shí)現(xiàn)和應(yīng)用,特別準(zhǔn)備了模擬了File類,并且模擬了“文件下載”操作。
通過(guò)閱讀下方代碼可以發(fā)現(xiàn):對(duì)于File類,內(nèi)部狀態(tài)是pool屬性和download方法;外部狀態(tài)是name和src(文件名和文件鏈接)。借助對(duì)象池,實(shí)現(xiàn)了File類的復(fù)用。
注:為了方便演示,Javascript實(shí)現(xiàn)的是并發(fā)操作,Python實(shí)現(xiàn)的是串行操作。輸出結(jié)果略有不同。
3.1 Python3 實(shí)現(xiàn)from time import sleep class ObjectPool: # 通用對(duì)象池 def __init__(self): self.__pool = [] # 創(chuàng)建對(duì)象 def create(self, Obj): # 對(duì)象池中沒(méi)有空閑對(duì)象,則創(chuàng)建一個(gè)新的對(duì)象 # 對(duì)象池中有空閑對(duì)象,直接取出,無(wú)需再次創(chuàng)建 return self.__pool.pop() if len(self.__pool) > 0 else Obj(self) # 對(duì)象回收 def recover(self, obj): return self.__pool.append(obj) # 對(duì)象池大小 def size(self): return len(self.__pool) class File: # 模擬文件對(duì)象 def __init__(self, pool): self.__pool = pool def download(self): # 模擬下載操作 print("+ 從", self.src, "開(kāi)始下載", self.name) sleep(0.1) print("-", self.name, "下載完成") # 下載完畢后,將對(duì)象重新放入對(duì)象池 self.__pool.recover(self) if __name__ == "__main__": obj_pool = ObjectPool() file1 = obj_pool.create(File) file1.name = "文件1" file1.src = "https://download1.com" file1.download() file2 = obj_pool.create(File) file2.name = "文件2" file2.src = "https://download2.com" file2.download() file3 = obj_pool.create(File) file3.name = "文件3" file3.src = "https://download3.com" file3.download() print("*" * 20) print("下載了3個(gè)文件, 但其實(shí)只創(chuàng)建了", obj_pool.size(), "個(gè)對(duì)象")
輸出結(jié)果(這里為了方便演示直接使用了sleep方法,沒(méi)有再用多線程模擬):
+ 從 https://download1.com 開(kāi)始下載 文件1 - 文件1 下載完成 + 從 https://download2.com 開(kāi)始下載 文件2 - 文件2 下載完成 + 從 https://download3.com 開(kāi)始下載 文件3 - 文件3 下載完成 ******************** 下載了3個(gè)文件, 但其實(shí)只創(chuàng)建了 1 個(gè)對(duì)象3.2 ES6 實(shí)現(xiàn)
// 對(duì)象池 class ObjectPool { constructor() { this._pool = []; // } // 創(chuàng)建對(duì)象 create(Obj) { return this._pool.length === 0 ? new Obj(this) // 對(duì)象池中沒(méi)有空閑對(duì)象,則創(chuàng)建一個(gè)新的對(duì)象 : this._pool.shift(); // 對(duì)象池中有空閑對(duì)象,直接取出,無(wú)需再次創(chuàng)建 } // 對(duì)象回收 recover(obj) { return this._pool.push(obj); } // 對(duì)象池大小 size() { return this._pool.length; } } // 模擬文件對(duì)象 class File { constructor(pool) { this.pool = pool; } // 模擬下載操作 download() { console.log(`+ 從 ${this.src} 開(kāi)始下載 ${this.name}`); setTimeout(() => { console.log(`- ${this.name} 下載完畢`); // 下載完畢后, 將對(duì)象重新放入對(duì)象池 this.pool.recover(this); }, 100); } } /****************** 以下是測(cè)試函數(shù) **********************/ let objPool = new ObjectPool(); let file1 = objPool.create(File); file1.name = "文件1"; file1.src = "https://download1.com"; file1.download(); let file2 = objPool.create(File); file2.name = "文件2"; file2.src = "https://download2.com"; file2.download(); setTimeout(() => { let file3 = objPool.create(File); file3.name = "文件3"; file3.src = "https://download3.com"; file3.download(); }, 200); setTimeout( () => console.log( `${"*".repeat(50)} 下載了3個(gè)文件,但其實(shí)只創(chuàng)建了${objPool.size()}個(gè)對(duì)象` ), 1000 );
輸出結(jié)果如下:
+ 從 https://download1.com 開(kāi)始下載 文件1 + 從 https://download2.com 開(kāi)始下載 文件2 - 文件1 下載完畢 - 文件2 下載完畢 + 從 https://download3.com 開(kāi)始下載 文件3 - 文件3 下載完畢 ************************************************** 下載了3個(gè)文件,但其實(shí)只創(chuàng)建了2個(gè)對(duì)象4. 參考
《JavaScript 設(shè)計(jì)模式和開(kāi)發(fā)實(shí)踐》
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42837.html
摘要:作者按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用和兩種語(yǔ)言實(shí)現(xiàn)。享元模式提醒我們將一個(gè)對(duì)象的屬性劃分為內(nèi)部和外部狀態(tài)。 作者按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript和python兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)現(xiàn)方式,但此小冊(cè)只記錄最直截了當(dāng)?shù)膶?shí)現(xiàn)方式 :) 個(gè)人技術(shù)博客-godbmw.com 歡迎來(lái)玩! 每周至少 1 篇原創(chuàng)...
摘要:而享元模式的核心就是運(yùn)用共享技術(shù)來(lái)有效支持大量細(xì)粒度的對(duì)象。享元模式要求將對(duì)象的屬性劃分為內(nèi)部狀態(tài)和外部狀態(tài),所以在了解享元模式之前我們先要了解兩個(gè)概念內(nèi)部狀態(tài)外部狀態(tài)。一般情況下在這四種情況下應(yīng)該考慮使用享元模式。 享元模式(flyweight)是一種用于性能優(yōu)化的模式,之所以用fly其意為蠅量級(jí)。而享元模式的核心就是運(yùn)用共享技術(shù)來(lái)有效支持大量細(xì)粒度的對(duì)象。雖然面向?qū)ο罂梢苑浅7奖愕?..
摘要:類圖相關(guān)的設(shè)計(jì)模式享元模式和代理模式當(dāng)代理模式消耗性能比較大的時(shí)候,就可以用享元模式享元模式和單例模式容器單例,享元模式就是復(fù)用對(duì)象的思想。源碼中的享元模式源碼地址享元模式參考慕課網(wǎng)設(shè)計(jì)模式精講設(shè)計(jì)模式讀書(shū)筆記享元模式 0x01.定義與類型 定義:提供了減少對(duì)象數(shù)量從而改善應(yīng)用所需的對(duì)象結(jié)構(gòu)的方法,系統(tǒng)使用少量對(duì)象,而且這些都比較相似,狀態(tài)變化小,可以實(shí)現(xiàn)對(duì)象的多次復(fù)用。 運(yùn)用共享技...
摘要:享元模式享元模式是一種優(yōu)化程序性能的模式本質(zhì)為減少對(duì)象創(chuàng)建的個(gè)數(shù)。 享元模式 享元模式是一種優(yōu)化程序性能的模式, 本質(zhì)為減少對(duì)象創(chuàng)建的個(gè)數(shù)。 以下情況可以使用享元模式:有大量相似的對(duì)象, 占用了大量?jī)?nèi)存對(duì)象中大部分狀態(tài)可以抽離為外部狀態(tài) demo某商家有 50 種男款內(nèi)衣和 50 種款女款內(nèi)衣, 要展示它們 方案一: 造 50 個(gè)塑料男模和 50 個(gè)塑料女模, 讓他們穿上展示, 代碼如...
摘要:享元模式通過(guò)分析應(yīng)用程序的對(duì)象,將其解析為內(nèi)在數(shù)據(jù)和外在數(shù)據(jù),減少對(duì)象數(shù)量,從而提高程序的性能。通過(guò)這種方式進(jìn)行事件綁定,可以減少事件處理程序的數(shù)量,這種方式叫做事件委托,也是運(yùn)用了享元模式的原理。事件處理程序是公用的內(nèi)在部分,每個(gè)菜單項(xiàng)各 github 全文地址 : YOU-SHOULD-KNOW-JS JavaScript設(shè)計(jì)模式之外觀模式 概念 外觀模式:為一組復(fù)雜子系統(tǒng)接口提...
閱讀 1151·2021-11-25 09:43
閱讀 1583·2021-10-25 09:47
閱讀 2478·2019-08-30 13:46
閱讀 764·2019-08-29 13:45
閱讀 1292·2019-08-26 13:29
閱讀 3000·2019-08-23 15:30
閱讀 1113·2019-08-23 14:17
閱讀 1336·2019-08-23 13:43