Design Patterns - Component
Composite(組合) — 物件結構型模式
當有將物件組合成樹形結構來表示“部分 - 整體” 的層次結構時,我們可以使用 Composite 模式,Composite 使得使用者對單個物件和組合物件的使用具有一致性。
適用場景
- 你想表示物件的部分 - 整體層次結構。
- 你想使用者忽略組合物件與單個物件的不同,使用者將統一地使用組合結構中的物件。
UML 圖
效果
- 定義了包含基本物件和組合物件的類層次機構:基本物件可以被組合成更復雜的組合物件,而這個組合物件又可以被組合,這樣不斷地遞迴下去。客戶程式碼中,任何用到基本物件的地方都可以使用組合物件。
- 簡化客戶程式碼:客戶可以一致的使用組合結構和單個物件。通常使用者不知道(也不關心)處理的是一個葉結點還是一個組合元件。這就簡化了客戶程式碼,因為在定義組合的那些類中不需要寫一些充斥著選擇語句的函式。
- 使得更容易增加新型別的元件:新定義的 Composite 或 Leaf 子類自動地與已有的結構的客戶程式碼一起工作,客戶程式不需要因新的 Component 類而改變。
- 使你的設計變得更加一般化:容易增加新元件也會產生一些問題,那就是很難限制組合中的元件。有時你希望一個組合只能有某些特定的元件。使用 Composite 時,你不能依賴型別系統施加這些約束,而必須在執行時進行檢查。
幾個問題
-
最大化 Component 介面:
Composite 模式的目的之一是使得使用者不知道他們正在使用具體的 Leaf 類和 Composite 類。為了達到這一目的,Composite 類應為 Leaf 和 Composite 類儘可能多定義一些公共操作。Composite 類通常為這些操作提供預設的實現,而 Leaf 和Composite 子類可以對它們進行重定義。
然而,這個目標有時可能會與類層次結構設計原則相沖突,該原則規定:一個類只能定義那些對它的子類有意義的操作。有許多 Component 所支援的操作對 Leaf 類似乎沒有什麼意義,那麼 Component 怎樣為它們提供一個預設的操作呢?
即把 Leaf 看成一個沒有子節點的 Component,就可以在 Component 類中定義一個預設的操作。 -
宣告管理子部件的操作:
雖然 Composite 類實現了 Add 和 Remove 操作用於管理子部件,但在 Composite 模式中一個重要的問題是:在 Composite 類層次結構中那些類宣告這些操作。我們是應該在 Component 中宣告這些操作,並使這些操作對 Leaf 類有意義,還是隻應該在 Composite 和它的子類中宣告並定義這些操作呢?
這需要在安全性和透明性之間做出選擇。- 在類層次結構的根部定義子節點管理介面的方法具有良好的透明性,因為你可以一致的使用所有的元件,但是這一方法是以安全性為代價的,因為客戶有可能會做一些無意義的事情,例如在 Leaf 中增加和刪除物件等。
- 在 Composite 類中定義管理子部件的方法具有良好的安全性,因為在像 C++ 這樣的靜態型別語言中,在編譯時任何從 Leaf 中增加或刪除物件的嘗試都會被發現。但這又損失了透明性,因為 Leaf 和 Composite 具有不同的介面。
在這一模式中,相對於安全性,我們比較強調透明性。如果你選擇了安全性,有時你可能會丟失型別資訊,並且不得不將一個元件轉換成一個組合。這樣的型別轉換必定不是安全的。
示例
# coding=utf-8
class Component:
def __init__(self, name):
self.name = name
def add(self, comp):
pass
def remove(self, comp):
pass
def display(self, depth):
pass
class Leaf(Component):
def display(self, depth):
strtemp = ''
for i in range(depth):
strtemp += '---'
print(strtemp + self.name)
class Composite(Component):
def __init__(self, name):
super(Composite, self).__init__(name)
self.children = []
def add(self, comp):
self.children.append(comp)
def remove(self, comp):
self.children.remove(comp)
def display(self, depth):
strtemp = ''
for i in range(depth):
strtemp += '---'
print(strtemp + self.name)
for comp in self.children:
comp.display(depth + 2)
client
if __name__ == "__main__":
root = Composite('根')
root.add(Leaf('葉1a'))
root.add(Leaf('葉1b'))
root.add(Leaf('花1a'))
root.add(Leaf('花1b'))
comp1a = Composite('枝1a')
comp1b = Composite('枝1b')
root.add(comp1a)
root.add(comp1b)
comp1a.add(Leaf('葉2a'))
comp1a.add(Leaf('葉2b'))
comp1a.add(Leaf('花2a'))
comp1a.add(Leaf('花2b'))
comp2a = Composite('枝2a')
comp1a.add(comp2a)
comp1b.add(Leaf('葉2a'))
comp1b.add(Leaf('花2a'))
comp2a.add(Leaf('葉3a'))
comp2a.add(Leaf('花3a'))
comp3a = Composite('枝3a')
comp2a.add(comp3a)
comp3a.add(Leaf('葉4a'))
comp3a.add(Leaf('花4a'))
root.display(1)
"""
output:
---根
---------葉1a
---------葉1b
---------花1a
---------花1b
---------枝1a
---------------葉2a
---------------葉2b
---------------花2a
---------------花2b
---------------枝2a
---------------------葉3a
---------------------花3a
---------------------枝3a
---------------------------葉4a
---------------------------花4a
---------枝1b
---------------葉2a
---------------花2a
Process finished with exit code 0
"""
相關文章
- Design Patterns 之工廠模式模式
- Design Patterns in Android:裝飾模式Android模式
- Design Patterns in Android:責任鏈模式Android模式
- [Patterns] ABT
- Digital PatternsGit
- React PatternsReact
- Concurrency Patterns in GoGo
- Advanced-react-patterns(2)React
- Glob Patterns匹配模式使用模式
- Java 21 新特性:Record PatternsJava
- [翻譯]通訊模式(Communication Patterns)模式
- 什麼是@Component,@Component的作用是什麼
- 註解 @component
- HotSpot JVM ComponentHotSpotJVM
- PostgreSQL DBA(124) - Develop(Putting multiple LIKE patterns into an array)SQLdev
- Components 與 Patterns 究竟有什麼區別
- design for failureAI
- Design ten
- Aura Component Skills & Tools
- React 手稿 – Component stateReact
- 初識 Web ComponentWeb
- Ant Design 官方《Ant Design 實戰教程》釋出
- Design Compiler(一)Compile
- STL and Design Pattern
- System design summary
- Design a Moore FSM
- System Design InterviewView
- Relationship Database DesignDatabase
- Ant Design VueVue
- [Vue Form] Basic Select componentVueORM
- PowerApps Component Framework PCF 部署APPFramework
- UI Component in CRM WebUI and HybrisUIWeb
- spring boot 註解@ComponentSpring Boot
- Symfony\Component\Debug\Exception\FatalErrorExceptionExceptionError
- React 的 PureComponent Vs ComponentReact
- @bean和@component的理解Bean
- [Design Pattern] Upload big file - 3. Code Design - part 1
- Decadal shifts in wind patterns reduced continental outflow and suppressed ozone trend in the 201...