Composite(組合模式)屬於結構型模式,是一種統一管理樹形結構的抽象方式。前端
意圖:將對象組合成樹形結構以表示 「部分 - 總體」 的層次結構。Composite 使得用戶對單個對象和組合對象的使用具備一致性。git
若是看不懂上面的意圖介紹,沒有關係,設計模式須要在平常工做裏用起來,結合例子能夠加深你的理解,下面我準備了三個例子,讓你體會什麼場景下會用到這種設計模式。github
公司組織關係可能分爲部門與人,其中人屬於部門,有的人有下屬,有的人沒有下屬。若是咱們統一將部門、人抽象爲組織節點,就能夠方便的統計某個部門下有多少人、財務數據等等,而不用關心當前節點是部門仍是人。typescript
操做系統的文件夾與文件也是典型的樹狀結構,爲了方便遞歸出文件夾內文件數量或者文件總大小,咱們最好設計的時候就將文件夾與文件抽象爲文件,這樣每一個節點都擁有相同的方法添加、刪除、查找子元素,而不須要關心當前節點是文件夾或是文件。設計模式
容器與組件的關係很小,用戶經常認爲容器也是一種組件,但搭建平臺實現時,容器與組件稍有不一樣,不一樣之處在於容器能夠嵌套子元素,而組件不能夠。若是所以搭建平臺就將組件分爲容器與組件,會致使 API 割裂爲兩套,不利於組件開發者維護與用戶理解,比較好的設計思路是將組件與容器統一當作組件,組件只是一種沒有子元素的特殊容器,這樣組件與容器就能夠擁有相同的 API,統一理解與操做了。微信
意圖:將對象組合成樹形結構以表示 「部分 - 總體」 的層次結構。Composite 使得用戶對單個對象和組合對象的使用具備一致性。函數
比較好理解,組合是指多個對象雖然有必定差別,但共同組合成了一個樹形結構,那麼對象之間就必定存在 「部分 - 總體」 的關係,組合模式要求咱們抽象一個對象 Component
做爲統一操做模型,葉子結點與非葉子結點都實現了全部功能,即使是沒有子元素的葉子結點,爲了強調透明性,仍是具有好比 getChildren
方法,只不過永遠都返回 null
。this
其中 Component
是組合中對象聲明接口,通常會實現全部公共類的全部接口,還要提供一個接口管理其子組件。spa
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
可能會失敗,其本質上仍是將節點的區別暴露給了業務層。
組合模式是針對樹狀結構這個特定場景的統一抽象方案,對下降系統複雜度有很重要的意義,同時也不要忘了過分抽象是有害的,咱們要拿捏其中的度。
下圖作了一個簡單的解釋:
程序中始終關注 Component
就好了,樹狀結構的差別已經被抹平。
討論地址是: 精讀《設計模式 - Composite 組合模式》· Issue #284 · dt-fe/weekly
若是你想參與討論,請 點擊這裏,每週都有新的主題,週末或週一發佈。前端精讀 - 幫你篩選靠譜的內容。
關注 前端精讀微信公衆號
版權聲明:自由轉載-非商用-非衍生-保持署名( 創意共享 3.0 許可證)