Fly Weight 享元模式

動(dòng)機(jī)

有些程序需要大量帶有內(nèi)部共享狀態(tài)的對(duì)象實(shí)例纺弊。作為例子阿逃,我們?cè)O(shè)想一個(gè)戰(zhàn)爭(zhēng)游戲卧波,里邊存在很多 soldier 對(duì)象时肿,soldier 對(duì)象維持著士兵行為的圖形化表示,如移動(dòng)和射擊港粱,另外還有士兵的生命值和在陣地中的位置螃成。雖然創(chuàng)建大量的 soldier 對(duì)象是必要的,但這會(huì)消耗大量的內(nèi)存查坪。

目的

此模式的目的是利用狀態(tài)共享來(lái)支撐需要大量實(shí)例對(duì)象的場(chǎng)景寸宏,這些對(duì)象有部分相同的內(nèi)部狀態(tài),另外一些則不一致偿曙。

實(shí)現(xiàn)

以下是享元模式的 UML 類圖 (Extrinsic State: 外部狀態(tài)氮凝, Intrinsic State: 內(nèi)部狀態(tài) )


  • Flyweight 聲明一個(gè)接口,通過(guò)這個(gè)接口享元接收并根據(jù)外部狀態(tài)采取行動(dòng)
  • ConcreteFlyweight 實(shí)現(xiàn) Flyweight 接口并保存內(nèi)部狀態(tài)望忆。ConcreteFlyweight 對(duì)象必須是可共享的罩阵。享元實(shí)例對(duì)象必須在保持內(nèi)部狀態(tài)的同時(shí)能夠?qū)ν獠繝顟B(tài)進(jìn)行操作。在戰(zhàn)爭(zhēng)游戲的例子里炭臭,圖形表示是內(nèi)部狀態(tài)永脓,位置和生命值是外部狀態(tài)。士兵移動(dòng)過(guò)程中鞋仍,動(dòng)作行為操作位置這個(gè)外部狀態(tài)從而產(chǎn)生新的位置常摧。
  • FlyweightFactory 此工廠新建和管理享元對(duì)象。此外威创,享元工廠確保享元對(duì)象的共享落午。工廠維持著一個(gè)包含各類享元的對(duì)象池。如果一類對(duì)象已經(jīng)創(chuàng)建過(guò)了肚豺,則直接從對(duì)象池中返回溃斋。如果是新的對(duì)象,則將其添加入對(duì)象池中吸申。
    在戰(zhàn)爭(zhēng)游戲的例子中梗劫,士兵的享元工廠創(chuàng)建兩種類型的享元:士兵享元和上校享元。當(dāng)客戶端請(qǐng)求獲取一個(gè)士兵時(shí)截碴,享元工廠檢查對(duì)象池中是否已有士兵對(duì)象梳侨,有的話直接返回,沒(méi)有的話就新建一個(gè)士兵對(duì)象日丹,塞入池中并返回給客戶端走哺;下一次客戶端再請(qǐng)求士兵時(shí),將直接返回先前創(chuàng)建的士兵對(duì)象哲虾,不會(huì)再創(chuàng)建新的丙躏。
  • Client 客戶端維持享元對(duì)象的引用择示,此外還計(jì)算和維持外部狀態(tài)

如果客戶端需要一個(gè)享元對(duì)象,它會(huì)訪問(wèn)工廠來(lái)獲取晒旅。工廠檢查享元對(duì)象池栅盲,看請(qǐng)求的對(duì)象類型是否在池中,如果存在敢朱,則返回該對(duì)象的引用剪菱;如果不存在,工廠會(huì)創(chuàng)建該類對(duì)象拴签,將其加入對(duì)象池中孝常,并將其引用返回給客戶端。享元維持內(nèi)部狀態(tài)(我們創(chuàng)建享元來(lái)在大量對(duì)象中共享的狀態(tài))并提供方法來(lái)操作外部狀態(tài)(這些狀態(tài)在各個(gè)對(duì)象中各不相同)

適用范圍和例子

享元模式適用于適用存在大量對(duì)象的程序蚓哩,并且這些對(duì)象的一部分內(nèi)部狀態(tài)可以共享构灸,另外一部分狀態(tài)則有所不同。

示例 - 戰(zhàn)爭(zhēng)游戲

游戲?qū)嵗?個(gè) SoldierClient岸梨, 每個(gè) client 負(fù)責(zé)維護(hù)自己的內(nèi)部狀態(tài)喜颁,這些狀態(tài)對(duì)于士兵享元來(lái)說(shuō)是外部的。盡管實(shí)例化了5個(gè) client曹阔, 但是僅使用了一個(gè) Soldier 享元對(duì)象半开。


源碼:design-patterns/flyweigh/Soldier

再一個(gè)例子 - 文本編輯器

面向?qū)ο蟮奈谋揪庉嬈餍枰獎(jiǎng)?chuàng)建字符對(duì)象 Character 來(lái)表示文件中的每個(gè)字符。每個(gè)字符對(duì)象 Character 維護(hù)著它是什么字符赃份,是什么字體寂拆,字符的大小以及它在文件中的位置等信息。一個(gè)文件通常由及其龐大的字符對(duì)象集組成抓韩,也就會(huì)占用非常多的內(nèi)存纠永。注意,一般來(lái)說(shuō)字符的數(shù)量(數(shù)字谒拴,字母和其他特殊字符)是已知并且固定的尝江,而且能應(yīng)用于每個(gè)字符上的字體也是已知的;所以英上,通過(guò)創(chuàng)建管理字符類型信息(字母炭序,數(shù)字等)和字體信息的 Letter 字母享元,然后再創(chuàng)建只維護(hù)字符在文件中位置的Letter Client 字母消費(fèi)者對(duì)象苍日, 我們就大大降低了編輯器的內(nèi)存需求惭聂。
源碼: design-patterns/flyweigh/character

總結(jié)

享元模式通過(guò)在消費(fèi)端共享享元對(duì)象來(lái)節(jié)省內(nèi)存消耗。所能節(jié)省的內(nèi)存量取決于享元種類的個(gè)數(shù)(如上面例子中討論的士兵分類和上校分類)易遣。

相關(guān)模式

工廠單例模式 - 享元模式一般會(huì)使用一個(gè)生產(chǎn)享元的工廠,并將單例應(yīng)用于這個(gè)工廠嫌佑,這樣每個(gè)種類的享元只會(huì)返回一個(gè)實(shí)例豆茫。
狀態(tài)策略模式 - 狀態(tài)和策略模式的對(duì)象也經(jīng)常實(shí)現(xiàn)為享元模式

JDK中的應(yīng)用

java.lang.Integer#valueOf(int) (also on Boolean, Byte, Character, Short, Long and BigDecimal)
Long 的內(nèi)部類 LongCache 即為享元對(duì)象池侨歉,其中緩存了 [-128, 127] 范圍的長(zhǎng)整型包裝類實(shí)例; 如果通過(guò) Long.valueOf(n) 獲取實(shí)例揩魂,在范圍內(nèi)的就直接從 LongCache 中返回幽邓; Long 在其內(nèi)部保存基本類型 long (注意是小寫)的值,并提供 parseLong, intValue, floatValue, longValue 等方法返回基本類型值的外部狀態(tài)火脉,正是符合享元模式的使用場(chǎng)景牵舵。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市倦挂,隨后出現(xiàn)的幾起案子畸颅,更是在濱河造成了極大的恐慌,老刑警劉巖方援,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件没炒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡犯戏,警方通過(guò)查閱死者的電腦和手機(jī)送火,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)先匪,“玉大人种吸,你說(shuō)我怎么就攤上這事⊙椒牵” “怎么了坚俗?”我有些...
    開(kāi)封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)姜钳。 經(jīng)常有香客問(wèn)我坦冠,道長(zhǎng),這世上最難降的妖魔是什么哥桥? 我笑而不...
    開(kāi)封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任辙浑,我火速辦了婚禮,結(jié)果婚禮上拟糕,老公的妹妹穿的比我還像新娘判呕。我一直安慰自己,他們只是感情好送滞,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布侠草。 她就那樣靜靜地躺著,像睡著了一般犁嗅。 火紅的嫁衣襯著肌膚如雪边涕。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音功蜓,去河邊找鬼园爷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛式撼,可吹牛的內(nèi)容都是我干的童社。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼著隆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼扰楼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起美浦,我...
    開(kāi)封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤弦赖,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后抵代,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體腾节,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年荤牍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了案腺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡康吵,死狀恐怖劈榨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晦嵌,我是刑警寧澤同辣,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站惭载,受9級(jí)特大地震影響旱函,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜描滔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一棒妨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧含长,春花似錦券腔、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至陪腌,卻和暖如春辱魁,著一層夾襖步出監(jiān)牢的瞬間烟瞧,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工染簇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留燕刻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓剖笙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親请唱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弥咪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1 場(chǎng)景問(wèn)題# 1.1 加入權(quán)限控制## 考慮這樣一個(gè)問(wèn)題,給系統(tǒng)加入權(quán)限控制十绑,這基本上是所有的應(yīng)用系統(tǒng)都有的功能...
    七寸知架構(gòu)閱讀 2,471評(píng)論 1 57
  • 享元模式(Flyweight Pattern):運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度對(duì)象的復(fù)用聚至。系統(tǒng)只使用少量的對(duì)象,...
    breezedancer閱讀 1,912評(píng)論 2 51
  • 定義 Flyweight在拳擊比賽中指最輕量級(jí)本橙,即“蠅量級(jí)”或“雨量級(jí)”扳躬。這里選擇使用“享元模式”的意譯,是因?yàn)檫@...
    步積閱讀 1,606評(píng)論 0 2
  • 當(dāng)年看西游甚亭,看的是熱鬧贷币;而今回頭看,所謂西游亏狰,前行的是人役纹,更重要的是心。 唐僧西行若心猿意馬暇唾,再牛逼的悟...
    水清知沉耳閱讀 219評(píng)論 0 0
  • 總以為這輩子的酸甜苦辣 像是歸結(jié)在一張餅上的滋味 半邊甜美策州,半邊苦澀 小時(shí)候 拼命去啃噬那甜美的半張 像是活在蜜罐...
    聽(tīng)那冷雨閱讀 289評(píng)論 0 3