1 意圖
將對象組合成樹形結構以表示“部分-整體”的層次結構。Composite使得用戶對單個對象和組合對象的使用具有一致性。
2 動機
在繪圖編輯器和圖形捕捉系統(tǒng)這樣的圖形應用程序中,用戶可以使用簡單的組件創(chuàng)建復雜的圖表。用戶可以組合多個簡單組件以形成一些較大的組件,這些組件又可以組合成更大的組件。一個簡單的實現(xiàn)方法是為Text和Line這樣的圖元定義一些類,另外定義一些類作為這些圖元的容器類( Container )。
然而這種方法存在一個問題:使用這些類的代碼必須區(qū)別對待圖元對象與容器對象,而實際上大多數(shù)情況下用戶認為它們是一樣的。對這些類區(qū)別使用,使得程序更加復雜。Composite模式描述了如何使用遞歸組合,使得用戶不必對這些類進行區(qū)別,如下圖所示。

Composite模式的關鍵是一個抽象類,它既可以代表圖元,又可以代表圖元的容器。在圖形系統(tǒng)中的這個類就是Graphic,它聲明一些與特定圖形對象相關的操作,例如Draw。同時它也聲明了所有的組合對象共享的一些操作,例如一些操作用于訪問和管理它的子部件。
Picture類定義了一個Graphic 對象的聚合。Picture 的Draw操作是通過對它的子部件調用Draw實現(xiàn)的,Picture還用這種方法實現(xiàn)了一些與其子部件相關的操作。由于Picture接口與Graphic接口是一致的,因此Picture對象可以遞歸地組合其他Picture對象。
下圖是一個典型的由遞歸組合的Graphic對象組成的組合對象結構。

3 適用性
以下情況使用Composite模式:
- 你想表示對象的部分-整體層次結構
- 你希望用戶忽略組合對象與單個對象的不同,用戶將統(tǒng)一地使用組合結構中的所有對象
4 結構

典型的Composite對象結構如下圖所示:

5 參與者
- component(Graphic)
——為組合中的對象聲明接口
——在適當?shù)那闆r下,實現(xiàn)所有類共有接口的缺省行為
——聲明一個接口用于訪問和管理Component的子組件
——(可選)在遞歸結構中定義一個接口,用于訪問一個父部件,并在合適的情況下實現(xiàn)它。 - Leaf(Rectangle、Line、Text等)
——在組合中表示葉節(jié)點對象,葉節(jié)點沒有子節(jié)點
——在組合中定義圖元對象的行為 - Composite(Picture)
——定義有子部件的那些部件的行為
——存儲子部件
——在Component接口中實現(xiàn)與子部件有關的操作 - Client
——通過Component接口操作組合部件的對象
6 協(xié)作
用戶使用Component類接口與組合結構中的對象進行交互。如果接收者是一個葉節(jié)點,則直接處理請求。如果接受者是Composite,它通常將請求發(fā)送給它的子部件,在轉發(fā)請求之前或之后可能執(zhí)行一些輔助操作。
7 效果
- 1 定義了包含基本對象和組合對象的類層次結構,基本對象可以被組合成更復雜的組合對象,而這個組合對象又可以被組合;
- 2 簡化客戶代碼:客戶可以一致地使用組合結構和單個對象;
- 3 使得更容易增加新類型的組件;
- 4 使你的設計變得更加一般化。
8 實現(xiàn)
要考慮的問題:
- 1 顯式的父部件引用:保持從子部件到父部件的引用能簡化組合結構的遍歷和管理;
- 2 共享組件;
- 3 最大化Component接口;
- 4 聲明管理子部件的操作;
- 5 Component是否應該實現(xiàn)一個Component列表;
- 6 子部件排序;
- 7 使用高速緩沖存貯改善性能;
- 8 應該由誰刪除Component
- 9 存貯組件最好用哪一種數(shù)據(jù)結構;