溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Flyweight享元模式怎么實現

發布時間:2022-03-25 10:46:58 來源:億速云 閱讀:145 作者:iii 欄目:web開發

今天小編給大家分享一下Flyweight享元模式怎么實現的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

Flyweight(享元模式)

Flyweight(享元模式)屬于結構型模式,是一種共享對象的設計模式。

意圖:運用共享技術有效地支持大量細粒度的對象。

舉例子

如果看不懂上面的意圖介紹,沒有關系,設計模式需要在日常工作里用起來,結合例子可以加深你的理解,下面我準備了三個例子,讓你體會什么場景下會用到這種設計模式。

富文本編輯器的字母對象

富文本編輯器在英文環境下,其中的文本由大量字母組成,為了便于做統一的格式化、計算等處理,需要將每個字母都存儲為對象,但這樣存儲的代價太大了。

已知英文字母一共 26 個,所以文檔中存在大量重復使用的字母,而每個字母除了位置信息外,其它信息都是相同且只讀的,那么有辦法降低富文本場景巨大的字母對象數量嗎?

網盤存儲

當我們上傳一部電影時,有時候幾十 GB 的內容不到一秒就上傳完了,這是網盤提示你,“已采用極速技術秒傳”,你會不會心生疑惑,這么厲害的技術為什么不能每次都生效?

另外,網盤存儲時,同一部電影可能都會存放在不同用戶的不同文件夾中,而且電影文件又特別巨大,和富文本類似,電影文件也只有存放位置是不同的,而其余內容都特別巨大且只讀,有什么辦法能優化存儲呢?

大型多人游戲

玩多人游戲時,為了防止外掛,一般對象的創建與計算是在服務器完成的,那如何保證一個玩家拾取物品后,另一個玩家看到的物品會消失?

其實道理已經不言而喻了,雖然在不同客戶端之間,游戲對象是相互獨立的,但在一局游戲中,所有玩家的對象在服務器是共享的。

意圖解釋

“共享” 就是享元模式的精髓,將那些大量的,具有很多內部狀態而外部狀態很少的對象進行共享,就是享元模式的使用方式。

意圖:運用共享技術有效地支持大量細粒度的對象。

共享技術可以理解為緩存,當一個對象創建后,再次訪問相同對象時,就不再創建新的對象了,而只有在訪問沒有被緩存過的對象時,才創建新對象,并立即緩存起來。

這樣做可以有效支持大量細粒度的對象,在富文本例子中,無數的字母就是大量細粒度對象,在網盤存儲中,電影文件就是大量細粒度對象,在大型多人游戲中,每局游戲內存在大量細粒度對象。

這些細粒度對象都擁有相同的特征:

量特別大,這個很容易理解。

具有大量內部狀態,且不隨著客戶端的不同而改變。

富文本的字母,不因為展示到不同語句中而發生變化,變化的只有狀態;電影文件,不因為放在不同用戶的文件夾中而對電影內容產生變化,變化的只有屬于哪些用戶,放在哪些文件夾里;多人游戲中,同一把武器對象,不因為有多個人的電腦獨立運行而擁有更多的彈藥,變化的只有在哪些客戶端被訪問。

具有少量外部狀態,甚至沒有外部狀態。在上面已經解釋了,字母的位置、電影的位置、游戲對象的客戶端都是外部狀態,這些外部狀態相比于其內部狀態來說,大小微乎其微,且方便分離存儲。

遇到這種情況,我們就可以將對象內部狀態共享,外部狀態獨立存儲,從而節省大量空間。

尤其是對于網盤的場景,承諾給用戶 2 TB 的存儲空間,這個用戶看到其他人分享了 100 個電影,就點擊 “下載到我的網盤”,此時雖然占用了自己 1 TB 的網盤空間,但實際上網盤運營商并沒有增加 1 TB 的存儲空間,實際可能增加了 1kb 的存儲空間,記錄了存儲位置,這就是網盤雞賊的地方,并不占用空間的內容,卻占用了用戶真金白銀購買的存儲空間。

當然,這就是享元模式的價值,對網盤公司來說,價值巨大,對用戶來說,沒有價值。所以享元模式的價值體現在全局,比如對整個富文本編輯器來說,減少了巨量字母對象數量,但對于每一個字母對象而言,并沒有任何優化。

結構圖

對于 Client 而言,下圖描述了如何共享 Flyweight:

Flyweight: 共享接口,通過這個接口可以操作對象的外部狀態。

ConcreteFlyweight: 實現 Flyweight 接口的對象,這個對象是可被共享的。

UnsharedConcreteFlyweight: 不被共享的對象,因為在享元模式中,實際上并不是所有對象都可以被共享。

FlyweightFactory: 創建并管理 Flyweight 對象,通過其返回的 Flyweight 對象,如果已創建,則會返回之前創建的那個,沒有的話才會創建一個新的。

Client: 使用 Flyweight 的客戶端。

通過第二個圖可以明顯看到,兩個不同的 Client 持有了相同 aConcreteFlyweight 引用。

代碼例子

下面例子使用 typescript 編寫。

class FlyweightFactory {

  public getFlyWeight(key) {

    if (this.flyweight[key]) {

      return this.flyweight[key]

    }

    const flyweight = new Flyweight()

    this.flyweight[key] = flyweight

    return flyweight

  }

}

FlyweightFactory 提供的 getFlyWeight 方法,實際上是按照 key 對 flyweight 實例進行緩存,相同 key 下只存儲一個 flyweight 實例。

弊端

如果細粒度對象不多,則沒必要使用享元模式。

另外,就算細粒度對象很多,如果對象內部狀態并不多,主要都是外部狀態,那么享元模式就起不到什么作用了,因為享元模式通過共享對象,只能節省內部狀態,而不能節省外部狀態。

另外,如果享元模式映射到的共享對象數量并沒有比原始對象少出數量級關系,使用的意義也不大。比如富文本編輯器的例子,對于英文來說,一共就 26 個字母,那么 1 萬字的文章優化比例是 10000:26,但對于中文文章而言,文字實例本身就很多,可能 1 萬字的文章中,漢字去重后依然有 3000 個,那么優化比例就是 10000:3000,此時享元模式的意義就沒那么打了。

以上就是“Flyweight享元模式怎么實現”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女