[Design Pattern] 組合模式 (Composite Pattern)

Andy Lu
5 min readMar 12, 2021

不知道你有沒有玩過樂高,每一款樂高都是由一堆基本磚所組合而成的,有不同的形狀以及顏色,我們在進行組裝時候,利用每一個基本磚組合而成一個又一個的物體。將每一個物體組合完成之後,再將每一個物體排在一起,那麼就會組合成一個主題。

這個概念,跟我們今天要介紹的組合模式有點相似。

組合模式

是一種將多個小物件組合成一個大物件的設計模式,其中每一個小物件的都有相同的使用方法。

如此一來,只需要針對每一個小物件來去實作即可,降低了複雜度,也提高了可擴充性。

換個角度來看,組合模式就是嘗試將一個大物件分解成多個具有相同操作的小物件。

在組合模式中,是將所有物件以樹狀圖的形式來組合,用來表示 “部分-整體”的結構。

模式分類

結構模式 (Structural Pattern)。

結構圖

成員

  • Component: 是一個抽象類別,組合模式中的物件都繼承此類別。其中, inflate() 是每一個物件都要實作的功能。 add(Component) 以及 remove(Component) 都是提供給 Composite 類別組合 Leaf 使用的。
  • Leaf : 是一個具象類別 (Concrete class),實作 Component 所定義的 inflate()方法,為一個最小單位的物件,在這裏不能包含其他 Leaf
  • Composite :同樣也是一個具象類別 (Concrete class),除了實作 Component 定義的 inflate() 方法。將多個 Leaf 紀錄在一個列表 components 裡利用 add(Component) 以及 remove(Component) 來對列表做處理。

將結構圖用程式碼來呈現:

  • 首先,定義一個 Component interface
  • 接者,實作 Leaf class

注意

  1. 因為 Component 中包含 add(Component) 以及 remove(Component) ,所以在 Leaf 類中,需要實作它們。但是,因為 Leaf 不包含其他的 Leaf ,所以這兩個方法都不需要實作。
  2. inflate() 為該 Leaf 所需執行的動作,在這邊我們簡單列印一下 name 即可。

接下來,我們來實作 Composite class

注意

跟 Leaf 不同, Composite 類需要儲存 Leaf ,所以這邊使用了 MutableList<Component>。 (用 mutableListOf<Component>() 可以取得一個 MutableList 實例),並且實作 add(Component) 以及 remove(Component)

在 Composites 中的 inflate() 方法中,我們利用 components.forEach 來依序執行儲存在此 Composite類的 Leaf 的 inflate() 方法。

  • 設定完兩個類別之後,我們看看要怎麼操作組合模式。

1. 將 Leaf 加到 Composite 類別中

2. 移除 Leaf

3. 將多個 Composite 嵌套在一起

結論

在組合模式中,將一個類別拆細,拆出多個 Leaf,並讓每一個 Leaf 都含有相同的方法,這樣子的好處可以讓原類別的程式碼減少。把 Leaf 的部分從原本的類別搬出去,並實作 Component,下次若有需要新增新的 Leaf 時,只需要新建立一個實作 Component 的新 Leaf,如此一來,在原類別上新增 Leaf 就變得很輕鬆簡單了。

在 Component 中,因為包含了 Composite 的 add(Component) 以及 remove(Component) ,所以在每一個 Leaf 中就會需要覆寫這兩個沒有用到的方法,在使用上就要小心一點,避免在 Leaf 中,實作不該實作的內容。

如果你覺得本篇文章不錯,請拍手👏鼓勵我~謝謝

gitHub: https://github.com/andyludeveloper/CompositePattern_Kotlin

--

--

Andy Lu

Android/Flutter developer, Kotlin Expert, like to learn and share.