一、從生活中領(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)。
三处坪、模型抽象
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)