Composite(組合模式)

Composite(組合模式)屬於結構型模式,是一種統一管理樹形結構的抽象方式。

意圖:將物件組合成樹形結構以表示 “部分 - 整體” 的層次結構。Composite 使得使用者對單個物件和組合物件的使用具有一致性。

舉例子

如果看不懂上面的意圖介紹,沒有關係,設計模式需要在日常工作裡用起來,結合例子可以加深你的理解,下面我準備了三個例子,讓你體會什麼場景下會用到這種設計模式。

公司組織關係樹

公司組織關係可能分為部門與人,其中人屬於部門,有的人有下屬,有的人沒有下屬。如果我們統一將部門、人抽象為組織節點,就可以方便的統計某個部門下有多少人、財務資料等等,而不用關心當前節點是部門還是人。

作業系統的資料夾與檔案

作業系統的資料夾與檔案也是典型的樹狀結構,為了方便遞迴出文件夾內檔案數量或者檔案總大小,我們最好設計的時候就將資料夾與檔案抽象為檔案,這樣每個節點都擁有相同的方法新增、刪除、查詢子元素,而不需要關心當前節點是資料夾或是檔案。

搭建平臺的元件與容器

容器與元件的關係很小,使用者常常認為容器也是一種元件,但搭建平臺實現時,容器與元件稍有不同,不同之處在於容器可以巢狀子元素,而元件不可以。如果因此搭建平臺就將元件分為容器與元件,會導致 API 割裂為兩套,不利於元件開發者維護與使用者理解,比較好的設計思路是將元件與容器統一看成元件,元件只是一種沒有子元素的特殊容器,這樣元件與容器就可以擁有相同的 API,統一理解與操作了。

意圖解釋

意圖:將物件組合成樹形結構以表示 “部分 - 整體” 的層次結構。Composite 使得使用者對單個物件和組合物件的使用具有一致性。

比較好理解,組合是指多個物件雖然有一定差異,但共同組合成了一個樹形結構,那麼物件之間就一定存在 “部分 - 整體” 的關係,組合模式要求我們抽象一個物件

Component

作為統一操作模型,葉子結點與非葉子結點都實現了所有功能,即便是沒有子元素的葉子結點,為了強調透明性,還是具備比如

getChildren

方法,只不過永遠都返回

null

結構圖

精讀《設計模式 - Composite 組合模式》

其中

Component

是組合中物件宣告介面,一般會實現所有公共類的所有介面,還要提供一個介面管理其子元件。

Leaf

表示葉子結點,沒有子結點,相應的

Composite

就是有子結點的節點。

可以看到,組合模式就是將樹狀結構中所有節點統一抽象了,

我們不需要關心葉子結點與非葉子結點的差異,而可以透過組合模式的抽象遮蔽掉這些差異,統一處理。

程式碼例子

下面例子使用 typescript 編寫。

// 統一的抽象

class Component {

// 新增子元素

public add() {}

// 獲取名稱

public getName() {}

// 獲取子元素

public getChildren() {}

}

// 非葉子結點

class Composite extends Component {

public add(component: Component) {

this。children。push(component)

}

public getName() {

return this。name

}

public getChildren() {

return this。children

}

}

// 葉子結點

class Leaf extends Component {

public add(component: Component) {

throw Error(‘葉子結點無法新增元素’)

}

public getName() {

return this。name

}

public getChildren() {

return null

}

}

最後我們把對所有節點的操作都轉為

Component

物件,而不用關心這個物件具體是

Composite

Leaf

弊端

組合模式進行了一層抽象,其實增加了複雜系統中業務複雜度。如果

Composite

Leaf

差異過大,那麼統一抽象帶來的理解成本是很高的。

同時,

Leaf

不得不實現一些僅

Composite

存在的空函式,比如

add

delete

,即便這些方法對他們是無意義的,此時可能要進行統一的無效或錯誤處理,才能使業務層真正不用感知他們的區別,否則

add

可能會失敗,其本質上還是將節點的區別暴露給了業務層。

總結

組合模式是針對樹狀結構這個特定場景的統一抽象方案,對降低系統複雜度有很重要的意義,同時也不要忘了過度抽象是有害的,我們要拿捏其中的度。

下圖做了一個簡單的解釋:

精讀《設計模式 - Composite 組合模式》

程式中始終關注

Component

就行了,樹狀結構的差異已經被抹平。

討論地址是:

精讀《設計模式 - Composite 組合模式》· Issue #284 · dt-fe/weekly

如果你想參與討論,請 點選這裡,每週都有新的主題,週末或週一釋出。前端精讀 - 幫你篩選靠譜的內容。

關注

前端精讀微信公眾號

精讀《設計模式 - Composite 組合模式》

版權宣告:自由轉載-非商用-非衍生-保持署名(

創意共享 3.0 許可證