天天看點

設計模式利劍15-組合模式

定      義:将對象組合成樹形結構以表示“整體-部分”的層次結構,使得使用者對單個對象群組合對象的使用具有一緻性

優      點:

               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