第十八章:享元模式

一、從生活中領(lǐng)悟享元模式

Tony參加一個團(tuán)體活動历造,活動中需要用到顏料甩十,而顏料是公用的,每個團(tuán)隊都需要派遣一名隊員去取用吭产。顏料有紅枣氧、黃、藍(lán)垮刹、綠、紫5大桶张弛。

模擬故事劇情
python

import logging


class Pigment:
    """顏料"""

    def __init__(self, color):
        self._color = color
        self._user = ""

    def getColor(self):
        return self._color

    def setUser(self, user):
        self._user = user
        return self

    def showInfo(self):
        print("%s 取得 %s 色顏料" % (self._user, self._color))


class PigmentFactory:
    """顏料的工廠類"""

    def __init__(self):
        self._sigmentSet = {
            "紅": Pigment("紅"),
            "黃": Pigment("黃"),
            "藍(lán)": Pigment("藍(lán)"),
            "綠": Pigment("綠"),
            "紫": Pigment("紫")
        }

    def getPigment(self, color):
        pigment = self._sigmentSet.get(color)
        if pigment is None:
            logging.error("沒有%s顏色的顏料荒典!", color)
        return pigment


def testPigment():
    factory = PigmentFactory()
    pigmentRed = factory.getPigment("紅").setUser("夢之隊")
    pigmentRed.showInfo()
    pigmentYellow = factory.getPigment("黃").setUser("夢之隊")
    pigmentYellow.showInfo()
    pigmentBlue1 = factory.getPigment("藍(lán)").setUser("夢之隊")
    pigmentBlue1.showInfo()
    pigmentBlue2 = factory.getPigment("藍(lán)").setUser("和平隊")
    pigmentBlue2.showInfo()


if __name__ == "__main__":
    testPigment()

輸出結(jié)果:

夢之隊 取得 紅 色顏料
夢之隊 取得 黃 色顏料
夢之隊 取得 藍(lán) 色顏料
和平隊 取得 藍(lán) 色顏料

Process finished with exit code 0

二、從劇情中思考享元模式

2.1 什么是享元模式

運用共享技術(shù)有效地支持大量細(xì)粒度對象的復(fù)用

2.2 設(shè)計思想

在故事劇情中吞鸭,我們通過限定顏料的數(shù)量并采用共享的方式來達(dá)到節(jié)約資源寺董、節(jié)約成本的目的,在程序的世界中這種方式叫享元模式(Flyweight Pattern)刻剥。Flyweight一詞來源于拳擊比賽遮咖,意思是“特輕量級”。用在程序設(shè)計中造虏,就是指享元模式要求能夠共享的對象必須是輕量級對象御吞,也就是細(xì)粒度對象,因此享元模式又稱為輕量級模式漓藕。
享元模式以共享的方式高效地支持大量的細(xì)粒度對象陶珠,享元對象能做到共享的關(guān)鍵是區(qū)分內(nèi)部狀態(tài)和外部狀態(tài)。
● 內(nèi)部狀態(tài)(Intrinsic State)是存儲在享元對象內(nèi)部并且不會隨環(huán)境改變而改變的狀態(tài)享钞,因此內(nèi)部狀態(tài)是可以共享的狀態(tài)揍诽,如故事劇情中顏料的顏色就是Pigment對象的內(nèi)部狀態(tài)。
● 外部狀態(tài)(Extrinsic State)是隨環(huán)境改變而改變的栗竖、不可以共享的狀態(tài)暑脆。享元對象的外部狀態(tài)必須由客戶端保存,并在享元對象被創(chuàng)建之后狐肢,在需要使用的時候再傳入享元對象內(nèi)部添吗,如故事劇情中顏料的使用者就是外部狀態(tài)。

三处坪、模型抽象

享元模式的類圖.png

Flyweight 是享元對象的抽象類根资,負(fù)責(zé)定義對象的內(nèi)部狀態(tài)和外部狀態(tài)的接口架专。FlyweightImpl是享元對象的具體實現(xiàn)者,負(fù)責(zé)具體業(yè)務(wù)(狀態(tài))的處理玄帕,如故事劇情中的Pigment部脚。UnshareFlyweightImpl是不可共享的對象,不能夠使用共享技術(shù)的對象(一般不會出現(xiàn)在享元工廠中)裤纹,只是實現(xiàn)了抽象類Flyweight的接口(或空實現(xiàn))委刘。FlyweightFactory是享元工廠,是享元模式的核心類鹰椒,其實就是享元對象的一個容器锡移,職責(zé)也非常清晰:負(fù)責(zé)享元對象的創(chuàng)建和容器中對象的管理。

3.1 模型說明

1.設(shè)計要點
享元模式的實現(xiàn)非常簡單漆际,在設(shè)計享元模式的程序時要注意兩個主要角色和四個設(shè)計要點淆珊。
兩個主要角色:
(1)享元對象(Flyweight):即你期望用來共享的對象,享元對象必須是輕量級對象奸汇,也就是細(xì)粒度對象施符。
(2)享元工廠(FlyweightFactory):享元模式的核心角色,負(fù)責(zé)創(chuàng)建和管理享元對象擂找。享元工廠提供一個用于存儲享元對象的享元池戳吝,用戶需要對象時,首先從享元池中獲取贯涎,如果享元池中不存在听哭,則創(chuàng)建一個新的享元對象返回給用戶,并在享元池中保存該新增對象塘雳。
四個設(shè)計要點:
(1)享元對象必須是輕量級陆盘、細(xì)粒度的對象。
(2)區(qū)分享元對象的內(nèi)部狀態(tài)和外部狀態(tài)粉捻。
(3)享元對象的內(nèi)部狀態(tài)和屬性一經(jīng)創(chuàng)建不會被隨意改變礁遣。因為如果可以改變,則A取得這個對象obj后肩刃,改變了其狀態(tài)祟霍,B再去取這個對象obj時就已經(jīng)不是原來的狀態(tài)了。
(4)使用對象時通過享元工廠獲取盈包,使得傳入相同的key時獲得相同的對象沸呐。
2.享元模式的優(yōu)缺點
優(yōu)點:
(1)可以極大減少內(nèi)存中對象的數(shù)量,使得相同對象或相似對象(內(nèi)部狀態(tài)相同的對象)在內(nèi)存中只保存一份呢燥。
(2)享元模式的外部狀態(tài)相對獨立崭添,而且不會影響其內(nèi)部狀態(tài),從而使得享元對象可以在不同的環(huán)境中被共享叛氨。
缺點:
(1)享元模式使得系統(tǒng)更加復(fù)雜呼渣,需要分離出內(nèi)部狀態(tài)和外部狀態(tài)棘伴,這使得程序的邏輯復(fù)雜化。
(2)享元對象的內(nèi)部狀態(tài)一經(jīng)創(chuàng)建不能被隨意改變屁置。

四焊夸、應(yīng)用場景

(1)一個系統(tǒng)有大量相同或者相似的對象,由于這類對象的大量使用蓝角,造成內(nèi)存的大量耗費阱穗。
(2)對象的大部分狀態(tài)都可以外部化,可以將這些外部狀態(tài)傳入對象中使鹅。
享元模式是一個考慮系統(tǒng)性能的設(shè)計模式揪阶,使用享元模式可以節(jié)約內(nèi)存空間,提高系統(tǒng)的性能患朱,因為它的這一特性鲁僚,在實際項目中使用得比較多。比如瀏覽器的緩存裁厅,就可以使用這個設(shè)計思想蕴茴,瀏覽器會將已打開頁面的圖片、文件緩存到本地姐直,如果在一個頁面中多次出現(xiàn)相同的圖片(即一個頁面中多個img標(biāo)簽指向同一個圖片地址),則只需要創(chuàng)建一個圖片對象蒋畜,在解析到img標(biāo)簽的地方多次重復(fù)顯示這個對象即可声畏。

摘錄來自
人人都懂設(shè)計模式:從生活中領(lǐng)悟設(shè)計模式:Python實現(xiàn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市姻成,隨后出現(xiàn)的幾起案子插龄,更是在濱河造成了極大的恐慌,老刑警劉巖科展,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件均牢,死亡現(xiàn)場離奇詭異,居然都是意外死亡才睹,警方通過查閱死者的電腦和手機(jī)徘跪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來琅攘,“玉大人垮庐,你說我怎么就攤上這事∥肭伲” “怎么了哨查?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長剧辐。 經(jīng)常有香客問我寒亥,道長邮府,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任溉奕,我火速辦了婚禮褂傀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘腐宋。我一直安慰自己紊服,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布胸竞。 她就那樣靜靜地躺著欺嗤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卫枝。 梳的紋絲不亂的頭發(fā)上煎饼,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音校赤,去河邊找鬼吆玖。 笑死,一個胖子當(dāng)著我的面吹牛马篮,可吹牛的內(nèi)容都是我干的沾乘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼浑测,長吁一口氣:“原來是場噩夢啊……” “哼翅阵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起迁央,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤掷匠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后岖圈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體讹语,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年蜂科,在試婚紗的時候發(fā)現(xiàn)自己被綠了顽决。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡导匣,死狀恐怖擎值,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情逐抑,我是刑警寧澤鸠儿,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響进每,放射性物質(zhì)發(fā)生泄漏汹粤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一田晚、第九天 我趴在偏房一處隱蔽的房頂上張望嘱兼。 院中可真熱鬧,春花似錦贤徒、人聲如沸芹壕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽踢涌。三九已至,卻和暖如春序宦,著一層夾襖步出監(jiān)牢的瞬間睁壁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工互捌, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留潘明,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓秕噪,卻偏偏與公主長得像钳降,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子腌巾,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

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