python 設計模式之組合模式Composite Pattern

 #引入一

文件夾對咱們來講很熟悉,文件夾裏面能夠包含文件夾,也能夠包含文件。html

那麼文件夾是個容器,文件夾裏面的文件夾也是個容器,文件夾裏面的文件是對象。python

 

 這是一個樹形結構編程

我們生活工做中經常使用的一種結構設計模式

文件是一個簡單對象,我直接打開就可使用。文件夾是複雜對象,由於裏面還有子文件夾 或者是文件。安全

 我在用這個文件夾的時候,我用相同的方式對待文件夾和文件。架構

其實這時候咱們就是在使用設計模式中的組合模式了了app

 

#引入二

這是從人家的博客上截的圖spa

公司的組織架構也是經常使用的樹形結構,也適合使用組合模式設計

 

 

#組合模式定義

 組合模式(Composite Pattern),又叫部分總體模式,是用於把一組類似的對象看成一個單一的對象。組合模式依據樹形結構來組合對象,用來表示部分以及總體層次。這種類型的設計模式屬於結構型模式,它建立了對象組的樹形結構。3d

這種模式建立了一個包含本身對象組的類。該類提供了修改相同對象組的方式。

 

 #使用場景

一、想表示對象的部分-總體層次結構(樹形結構)。

二、但願用戶忽略組合對象與單個對象的不一樣,用戶將統一地使用組合結構中

3‘若是你想要建立層次結構,並能夠在其中以相同的方式對待全部元素,那麼組合模式就是最理想的選擇

 

#涉及角色

百度百科粘過來的

1.Component 是組合中的對象聲明接口,在適當的狀況下,實現全部類共有接口的默認行爲。聲明一個接口用於訪問和管理Component子部件。
2.Leaf 在組合中表示葉子結點對象,葉子結點沒有子結點。

3.Composite 定義有枝節點行爲,用來存儲子部件,在Component接口中實現與子部件有關操做,如增長(add)和刪除(remove)等

 

 

 

#組合模式的優勢

 組合模式的主要優勢以下:

      (1) 組合模式能夠清楚地定義分層次的複雜對象,表示對象的所有或部分層次,它讓客戶端忽略了層次的差別,方便對整個層次結構進行控制。

      (2) 客戶端能夠一致地使用一個組合結構或其中單個對象,沒必要關心處理的是單個對象仍是整個組合結構,簡化了客戶端代碼。

      (3) 在組合模式中增長新的容器構件和葉子構件都很方便,無須對現有類庫進行任何修改,符合「開閉原則」。

      (4) 組合模式爲樹形結構的面向對象實現提供了一種靈活的解決方案,經過葉子對象和容器對象的遞歸組合,能夠造成複雜的樹形結構,但對樹形結構的控制卻很是簡單。

 

#組合模式的缺點

 組合模式的主要缺點以下:

      在增長新構件時很難對容器中的構件類型進行限制。有時候咱們但願一個容器中只能有某些特定類型的對象,例如在某個文件夾中只能包含文本文件,使用組合模式時,不能依賴類型系統來施加這些約束,由於它們都來自於相同的抽象層,在這種狀況下,必須經過在運行時進行類型檢查來實現,這個實現過程較爲複雜。

 

#組合模式有兩種

(1) 透明組合模式

      透明組合模式中,抽象構件Component中聲明瞭全部用於管理成員對象的方法,包括add()、remove()以及getChild()等方法,這樣作的好處是確保全部的構件類都有相同的接口。在客戶端看來,葉子對象與容器對象所提供的方法是一致的,客戶端能夠相同地對待全部的對象。透明組合模式也是組合模式的標準形式。

      透明組合模式的缺點是不夠安全,由於葉子對象和容器對象在本質上是有區別的。葉子對象不可能有下一個層次的對象,即不可能包含成員對象,所以爲其提供add()、remove()以及getChild()等方法是沒有意義的,這在編譯階段不會出錯,但在運行階段若是調用這些方法可能會出錯(若是沒有提供相應的錯誤處理代碼)。

 (2) 安全組合模式

  安全組合模式中,在抽象構件Component中沒有聲明任何用於管理成員對象的方法,而是在Composite類中聲明並實現這些方法。這種作法是安全的,由於根本不向葉子對象提供這些管理成員對象的方法,對於葉子對象,客戶端不可能調用到這些方法。

安全組合模式的缺點是不夠透明,由於葉子構件和容器構件具備不一樣的方法,且容器構件中那些用於管理成員對象的方法沒有在抽象構件類中定義,所以客戶端不能徹底針對抽象編程,必須有區別地對待葉子構件和容器構件。在實際應用中,安全組合模式的使用頻率也很是高,在Java AWT中使用的組合模式就是安全組合模式。

 

  #舉個栗子 (python實現組合模式)

#抽象一個組織類
class Component:
    def __init__(self,name):
        self.name=name

    def add(self,comp):
        pass
    def remove(slef,comp):
        pass
    def display(self,depth):
        pass

#葉子節點
class Leaf(Component):
    def add(self):
        print('不能添加子節點')
    def remove(self):
        print('不能刪除子節點')
    def display(self,depth):
        strtemp=''
        for i in range(depth):
            strtemp +='---'
        print(strtemp+self.name)

#枝節點
class Composite(Component):
    def __init__(self,name):
        self.name=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)

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)
    

 

 

 

參考

https://www.cnblogs.com/fxycm/p/4887680.html

https://baike.baidu.com/item/%E7%BB%84%E5%90%88%E6%A8%A1%E5%BC%8F/1441281

https://www.cnblogs.com/lfxiao/p/6816026.html

https://www.runoob.com/design-pattern/composite-pattern.html

https://www.jianshu.com/p/68ada9b3cff9

還有參考其餘連接,忘記貼地址了

相關文章
相關標籤/搜索