Python設(shè)計模式 - 組合模式

"""

組合模式缕题,將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)朗儒,組合模式使得用戶對單個對象和組合對象的使用具有一致性查坪。"""

"""

一個類定義的組合對象肪跋,它可以用名稱來存儲分層使用的字典歧蒋。

這個類是相同的分層字典,但它按名稱提供方法來添加/訪問/修改子元素州既,就像一個組合谜洽。

"""

def?normalize(val):

????"""?正常化一個特殊字符的字符串吴叶,以便它可以被用來作為一個Python對象一個屬性

????"""

????if?val.find('-')?!=?-1:

????????val?=?val.replace('-',?'_')

????return?val

def?denormalize(val):

????"""?非規(guī)范化一個字符串"""

????if?val.find('_')?!=?-1:

????????val?=?val.replace('_',?'-')

????return?val

class?SpecialDict(dict):

????"""

????字典類褥琐,允許其鍵直接訪問屬性

????"""

????def?__getattr__(self,?name):

????????if?name?in?self.__dict__:

????????????return?self.__dict__[name]

????????elif?name?in?self:

????????????return?self.get(name)

????????else:

????????????#?檢查非規(guī)范化的名字

????????????name?=?denormalize(name)

????????????if?name?in?self:

????????????????return?self.get(name)

????????????else:

????????????????raise?AttributeError('沒有屬性名稱?%s'?%?name)

????def?__setattr__(self,?name,?value):

????????if?name?in?self.__dict__:

????????????self.__dict__[name]?=?value

????????elif?name?in?self:

????????????self[name]?=?value

????????else:

????????????#?檢查非規(guī)范化的名字

????????????name2?=?denormalize(name)

????????????if?name2?in?self:

????????????????self[name2]?=?value

????????????else:

????????????????#?新屬性

????????????????self[name]?=?value

class?CompositeDict(SpecialDict):

????"""一類像一個層次詞典。

????這個類是基于組合設(shè)計模式"""

????ID?=?0

????def?__init__(self,?name=''):

????????if?name:

????????????self._name?=?name

????????else:

????????????self._name?=?''.join(('id#',?str(self.__class__.ID)))

????????????self.__class__.ID?+=?1

????????self._children?=?[]

????????#?鏈接到父親

????????self._father?=?None

????????self[self._name]?=?SpecialDict()

????def?__getattr__(self,?name):

????????if?name?in?self.__dict__:

????????????return?self.__dict__[name]

????????elif?name?in?self:

????????????return?self.get(name)

????????else:

????????????#??檢查非規(guī)范化的名字

????????????name?=?denormalize(name)

????????????if?name?in?self:

????????????????return?self.get(name)

????????????else:

????????????????#查看孩子列表

????????????????child?=?self.findChild(name)

????????????????if?child:

????????????????????return?child

????????????????else:

????????????????????attr?=?getattr(self[self._name],?name)

????????????????????if?attr:

????????????????????????return?attr

????????????????????raise?AttributeError('no?attribute?named?%s'?%?name)

????def?isRoot(self):

????????"""?Return?我是否根組件"""

????????#?如果我沒有父母晤郑,我的根節(jié)點(diǎn)

????????return?not?self._father

????def?isLeaf(self):

????????"""?Return?葉節(jié)點(diǎn)?"""

????????#?我是一片葉節(jié)點(diǎn)敌呈,如果我沒有孩子

????????return?not?self._children

????def?getName(self):

????????"""?返回ConfigInfo對象的名稱?"""

????????return?self._name

????def?getIndex(self,?child):

????????"""返回孩子ConfigInfo對象的'child'的索引"""

????????if?child?in?self._children:

????????????return?self._children.index(child)

????????else:

????????????return?-1

????def?getDict(self):

????????"""?返回包含的詞典"""

????????return?self[self._name]

????def?getProperty(self,?child,?key):

????????"""?返回屬性值"""

????????#?首先get孩子的字典

????????childDict?=?self.getInfoDict(child)

????????if?childDict:

????????????return?childDict.get(key,?None)

????def?setProperty(self,?child,?key,?value):

????????"""

????????設(shè)置屬性的“key”的值

????????"""

????????#首先get孩子的字典

????????childDict?=?self.getInfoDict(child)

????????if?childDict:

????????????childDict[key]?=?value

????def?getChildren(self):

????????"""?返回此對象的直接子列表?"""

????????return?self._children

????def?getAllChildren(self):

????????"""?返回此對象的所有子列表?"""

????????l?=?[]

????????for?child?in?self._children:

????????????l.append(child)

????????????l.extend(child.getAllChildren())

????????return?l

????def?getChild(self,?name):

????????"""

?????????用給定名稱返回直接子對象

????????"""

????????for?child?in?self._children:

????????????if?child.getName()?==?name:

????????????????return?child

????def?findChild(self,?name):

????????"""

????????????從樹返回(用給定的名稱)子對象

????????"""

????????#?這將返回給定名稱的第一個子對象

????????#任何其他具有類似名稱的子對象不被考慮

????????for?child?in?self.getAllChildren():

????????????if?child.getName()?==?name:

????????????????return?child

????def?findChildren(self,?name):

????????"""?從樹返回給定名稱的子對象列表"""

????????#這將返回給定名稱的所有子項的列表贸宏,不論查詢的深度

????????children?=?[]

????????for?child?in?self.getAllChildren():

????????????if?child.getName()?==?name:

????????????????children.append(child)

????????return?children

????def?getPropertyDict(self):

????????"""?返回屬性字典"""

????????d?=?self.getChild('__properties')

????????if?d:

????????????return?d.getDict()

????????else:

????????????return?{}

????def?getParent(self):

????????return?self._father

????def?__setChildDict(self,?child):

????????"""

????????私有方法來設(shè)置子對象的'child'的字典在內(nèi)部字典

????????"""

????????d?=?self[self._name]

????????d[child.getName()]?=?child.getDict()

????def?setParent(self,?father):

????????self._father?=?father

????def?setName(self,?name):

????????"""

????????????設(shè)置此ConfigInfo對象的名稱為'name'

????????"""

????????self._name?=?name

????def?setDict(self,?d):

????????self[self._name]?=?d.copy()

????def?setAttribute(self,?name,?value):

????????self[self._name][name]?=?value

????def?getAttribute(self,?name):

????????return?self[self._name][name]

????def?addChild(self,?name,?force=False):

????????"""

????????添加一個新的子節(jié)點(diǎn)

????????如果可選標(biāo)志“force”設(shè)置為True,子對象被覆蓋磕洪,如果它已經(jīng)存在吭练。

????????該函數(shù)返回子對象,無論是新的或現(xiàn)有的

????????"""

????????if?type(name)?!=?str:

????????????raise?ValueError('Argument?should?be?a?string!')

????????child?=?self.getChild(name)

????????if?child:

????????????#?print('Child?%s?present!'?%?name)

????????????#?如果force==True?更換它

????????????if?force:

????????????????index?=?self.getIndex(child)

????????????????if?index?!=?-1:

????????????????????child?=?self.__class__(name)

????????????????????self._children[index]?=?child

????????????????????child.setParent(self)

????????????????????self.__setChildDict(child)

????????????return?child

????????else:

????????????child?=?self.__class__(name)

????????????child.setParent(self)

????????????self._children.append(child)

????????????self.__setChildDict(child)

????????????return?child

????def?addChild2(self,?child):

????????"""

????????添加子對象'child'析显。如果它已經(jīng)存在鲫咽,它由缺省覆蓋

????????"""

????????currChild?=?self.getChild(child.getName())

????????if?currChild:

????????????index?=?self.getIndex(currChild)

????????????if?index?!=?-1:

????????????????self._children[index]?=?child

????????????????child.setParent(self)

????????????????#?未設(shè)置現(xiàn)有的子節(jié)點(diǎn)的父級

????????????????currChild.setParent(None)

????????????????del?currChild

????????????????self.__setChildDict(child)

????????else:

????????????child.setParent(self)

????????????self._children.append(child)

????????????self.__setChildDict(child)

if?__name__?==?"__main__":

????window?=?CompositeDict('Window')

????frame?=?window.addChild('Frame')

????tfield?=?frame.addChild('Text?Field')

????tfield.setAttribute('size',?'20')

????btn?=?frame.addChild('Button1')

????btn.setAttribute('label',?'提交')

????btn?=?frame.addChild('Button2')

????btn.setAttribute('label',?'瀏覽')

????#print(window)

????#print(window.Frame)

????#print(window.Frame.Button1)

????#print(window.Frame.Button2)

????print(window.Frame.Button1.label)

????print(window.Frame.Button2.label)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市谷异,隨后出現(xiàn)的幾起案子分尸,更是在濱河造成了極大的恐慌,老刑警劉巖歹嘹,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件箩绍,死亡現(xiàn)場離奇詭異,居然都是意外死亡尺上,警方通過查閱死者的電腦和手機(jī)材蛛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怎抛,“玉大人卑吭,你說我怎么就攤上這事÷砭” “怎么了豆赏?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長富稻。 經(jīng)常有香客問我河绽,道長,這世上最難降的妖魔是什么唉窃? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮纹笼,結(jié)果婚禮上纹份,老公的妹妹穿的比我還像新娘。我一直安慰自己廷痘,他們只是感情好蔓涧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著笋额,像睡著了一般元暴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上兄猩,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天茉盏,我揣著相機(jī)與錄音鉴未,去河邊找鬼。 笑死鸠姨,一個胖子當(dāng)著我的面吹牛铜秆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播讶迁,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼连茧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了巍糯?” 一聲冷哼從身側(cè)響起啸驯,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎祟峦,沒想到半個月后罚斗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡搀愧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年惰聂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咱筛。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡搓幌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出迅箩,到底是詐尸還是另有隱情溉愁,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布饲趋,位于F島的核電站拐揭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏奕塑。R本人自食惡果不足惜堂污,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望龄砰。 院中可真熱鬧盟猖,春花似錦、人聲如沸换棚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽固蚤。三九已至娘汞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間夕玩,已是汗流浹背你弦。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工惊豺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鳖目。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓扮叨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親领迈。 傳聞我的和親對象是個殘疾皇子彻磁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

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

  • 參考文獻(xiàn): 《大話設(shè)計模式》——吳強(qiáng) 《Python設(shè)計模式》——pythontip.com 《23種設(shè)計模式》—...
    梁林張斌閱讀 2,276評論 0 4
  • 1、改變 UITextField 占位文字 顏色和去掉底部白框 [_userName setValue:[UICo...
    i_MT閱讀 1,041評論 0 2
  • *7月8日上午 N:Block :跟一個函數(shù)塊差不多狸捅,會對里面所有的內(nèi)容的引用計數(shù)+1衷蜓,想要解決就用__block...
    炙冰閱讀 2,489評論 1 14
  • “人在外頭,心在家尘喝。家里頭磁浇,放不下,是我的老爸老媽朽褪≈孟牛” 每當(dāng)聽到這首歌曲,不免也要跟著哼唱幾句缔赠。 是的衍锚,你在異鄉(xiāng)的...
    詼老斯閱讀 374評論 2 15
  • 一束花、一個蛋糕嗤堰、一桌菜戴质、我和她07年認(rèn)識相戀,2013年結(jié)婚踢匣,到現(xiàn)在2020年告匠,已經(jīng)相伴13年,如今我們是三口之...
    王繼軒24閱讀 111評論 0 1