Composite
動機(Motivation)
- 客戶代碼過多地依賴于對象容器復(fù)雜的內(nèi)部實現(xiàn)結(jié)構(gòu)膀斋,對象容器內(nèi)部實現(xiàn)結(jié)構(gòu)(而非抽象結(jié)構(gòu))的變化
引起客戶代碼的頻繁變化辽聊,帶來了代碼的維護性领虹、擴展性等弊端瘸洛。 - 如何將”客戶代碼與復(fù)雜的對象容器結(jié)構(gòu)“解耦奔誓?讓對象容器自己來實現(xiàn)自身的復(fù)雜結(jié)構(gòu)绎秒,從而使得客戶代碼就像處理簡單對象一樣來處理復(fù)雜的對象容器?
模式定義
將對象組合成樹形結(jié)構(gòu)以表示”部分-整體“的層次結(jié)構(gòu)呢灶。Composite使得用戶對單個對象和組合對象的使用具有一致性(穩(wěn)定)吴超。
——《設(shè)計模式》GoF
要點總結(jié)
- Composite模式采用 樹性結(jié)構(gòu) 來實現(xiàn)普遍存在的對象容器,從而將一對多的關(guān)系轉(zhuǎn)化為一對一的關(guān)系鸯乃,使得客戶代碼可以一致地(復(fù)用)處理對象和對象容器鲸阻,
無需關(guān)心處理的是單個的對象,還是組合的對象容器缨睡。 - 客戶代碼與純粹的抽象接口——而非對象容器的內(nèi)部實現(xiàn)結(jié)構(gòu)——發(fā)生依賴鸟悴,從而更能”應(yīng)對變化“。
- Composite模式在具體實現(xiàn)中奖年,可以讓父對象中的子對象反向追溯细诸;如果父對象有頻繁的遍歷需求,可使用緩存技術(shù)來改善效率陋守。
例子
# -*- coding:utf-8 -*-
class Component(object):
def __init__(self, node_name):
self.node_name = node_name
def process(self):
pass
class TreeNode(Component):
def __init__(self, node_name):
super(TreeNode, self).__init__(node_name)
self.node_list = []
def process(self):
self._process_cur_node()
self._process_sub_node()
def add_node(self, node):
self.node_list.append(node)
def remove_node(self, node):
self.node_list.pop(node)
def _process_cur_node(self):
print('process cur node:', self.node_name)
def _process_sub_node(self):
for sub_node in self.node_list:
sub_node.process()
class LeafNode(Component):
def process(self):
print('process leaf node:', self.node_name)
if __name__ == '__main__':
root_node = TreeNode('root')
tree_node1 = TreeNode('tree_node1')
tree_node2 = TreeNode('tree_node2')
tree_node3 = TreeNode('tree_node3')
leaf_node1 = LeafNode('leaf_node1')
leaf_node2 = LeafNode('leaf_node2')
root_node.add_node(tree_node1)
root_node.add_node(tree_node2)
tree_node1.add_node(tree_node3)
tree_node3.add_node(leaf_node1)
tree_node3.add_node(leaf_node2)
root_node.process()
輸出
('process cur node:', 'root')
('process cur node:', 'tree_node1')
('process cur node:', 'tree_node3')
('process leaf node:', 'leaf_node1')
('process leaf node:', 'leaf_node2')
('process cur node:', 'tree_node2')