定 義:将對象組合成樹形結構以表示“整體-部分”的層次結構,使得使用者對單個對象群組合對象的使用具有一緻性
優 點:
1、高層子產品調用簡單
2、節點自由增加
使用場景:
1 .你想表示對象的部分 - 整體層次結構
2 .你希望使用者忽略組合對象與單個對象的不同,使用者将統一地使用組合結構中的所有對象。
總結:組合模式解耦了客戶程式與複雜元素内部結構,進而使客戶程式可以向處理簡單元素一樣來處理複雜元素
實際應用:
先來看看組合模式的類圖設計:
1 . Composite 模式采用樹形結構來實作普遍存在的對象容器,進而将“一對多”的關系轉化“一對一”的關系,使得客戶代碼可以一緻地處理對象和對象容器,無需關心處理的是單個的對象,還是組合的對象容器。
2 .将“客戶代碼與複雜的對象容器結構”解耦是 Composite 模式的核心思想,解耦之後,客戶代碼将與純粹的抽象接口——而非對象容器的複内部實作結構——發生依賴關系,進而更能“應對變化”。
3 . Composite 模式中,是将“ Add 和 Remove 等和對象容器相關的方法”定義在“表示抽象對象的 Component 類”中,還是将其定義在“表示對象容器的 Composite 類”中,是一個關乎“透明性”和“安全性”的兩難問題,需要仔細權衡。這裡有可能違背面向對象的“單一職責原則”,但是對于這種特殊結構,這又是必須付出的代價。 ASP.NET 控件的實作在這方面為我們提供了一個很好的示範。
4 . Composite 模式在具體實作中,可以讓父對象中的子對象反向追溯;如果父對象有頻繁的周遊需求,可使用緩存技巧來改善效率
來看一個例子,用程式來實作一個複雜的算術表達式的時候,将複雜的算術表達式可以拆分成簡單的表達式,那麼複雜的表達式與簡單表達式組成了部分-整體的關系,也組合成一個樹形結構,那麼這種情況下,非常的适合用組合模式,例如(2+3)+(4*6),就可以組成一個樹形結構。用UML描述如下:
Public Class Corp
Private _name As String
Private _positon As String
Private _salary As Integer
Public Function getInfo() As String
Dim info As String = ""
info = "姓名:" & _name
info = info & " 職位:" & Me._positon
info = info & " 薪水:" & Me._salary
Return info
End Function
'''
''' <param name="__name"></param>
''' <param name="__position"></param>
''' <param name="__salary"></param>
Public Sub new(ByVal __name As String, ByVal __position As String, ByVal __salary As Integer)
Me._name = __name
Me._positon = __position
Me._salary = __salary
End Sub
End Class ' Corp
Public Class Branch
Inherits Corp
Private _branchArrayList As ArrayList = new ArrayList
'''
''' <param name="_corp"></param>
Public Sub addSubordinate(ByVal _corp As Corp)
_branchArrayList.Add(_corp)
End Sub
Public Function getSubordinateInfo() As ArrayList
Return _branchArrayList
End Function
'''
''' <param name="name"></param>
''' <param name="position"></param>
''' <param name="salary"></param>
Public Sub new(ByVal name As String, ByVal position As String, ByVal salary As Integer)
MyBase.New(name, position, salary)
End Sub
End Class ' Branch
Public Class Leaf
Inherits Corp
'''
''' <param name="name"></param>
''' <param name="position"></param>
''' <param name="salary"></param>
Public Sub new(ByVal name As String, ByVal position As String, ByVal salary As Integer)
MyBase.New(name, position, salary)
End Sub
End Class ' Leaf