代碼示例:https://github.com/elfc/patterns
分類
類對(duì)象結(jié)構(gòu)型
意圖
將對(duì)象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。Composite使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。
動(dòng)機(jī)
Composite模式允許創(chuàng)建樹型層次結(jié)構(gòu)來改變復(fù)雜性,同時(shí)允許結(jié)構(gòu)中的每一個(gè)元素操作同一個(gè)接口。該模式將對(duì)象組合成樹型結(jié)構(gòu)來表示整個(gè)或部分的層次結(jié)構(gòu)。這就意味著Composite模式允許客戶端使用單個(gè)對(duì)象或多個(gè)同一對(duì)象的組合。
適用性
- 想要表示對(duì)象的整個(gè)或者部分的層次結(jié)構(gòu)
- 想要客戶端能夠忽略符合對(duì)象和單個(gè)對(duì)象之間的差異。
- 結(jié)構(gòu)可以具有任何級(jí)別的復(fù)雜性,而且是動(dòng)態(tài)的。
優(yōu)點(diǎn)
- 定義了由主要對(duì)象和復(fù)合對(duì)象組成的類層次結(jié)構(gòu)。
- 使得添加新的組件類型更加簡(jiǎn)單。
- 提供了結(jié)構(gòu)的靈活性和可管理的接口。
結(jié)構(gòu)

參與者
- Component(GraphicComponent)
-- 為組合中的對(duì)象聲明接口。
-- 在適當(dāng)?shù)那闆r下,實(shí)現(xiàn)所有類共有接口的缺省行為。
-- 聲明一個(gè)接口用于訪問和管理Component的子組件。
-- (可選)在遞歸結(jié)構(gòu)中定義一個(gè)接口,用于訪問一個(gè)父部件,并在合適的情況下實(shí)現(xiàn)它。 - Leaf(LineLeaf、RectangleLeaf、TextLeaf)
-- 在組合中表示葉節(jié)點(diǎn)對(duì)象,葉結(jié)點(diǎn)沒有子結(jié)點(diǎn)。
-- 在組合中定義圖元對(duì)象的行為。 - Composite(PictureComposite)
-- 定義有子部件的那些部件的行為。
-- 存儲(chǔ)子部件。
-- 在Component接口中實(shí)現(xiàn)與子部件有關(guān)的操作。 - Client
-- 通過Component接口操縱組合部件的對(duì)象。
代碼示例
- 以下為透明模式的代碼示例
- 示例假設(shè)在繪圖編輯器和圖形捕捉系統(tǒng)這樣的圖形應(yīng)用程序中,用戶可以使用簡(jiǎn)單的組件創(chuàng)建復(fù)雜的圖表。
- Picture類定義了一個(gè)Graphic對(duì)象的聚合。Picture的Draw操作是通過對(duì)它的子部件調(diào)用Draw實(shí)現(xiàn)的,Picture還用這種方法實(shí)現(xiàn)了一些與其子部件相關(guān)的操作。由于Picture接口與Graphic接口是一致的,因此Picture對(duì)象可以遞歸地組合其他Picture對(duì)象。
/**
* @author chunyuliu
*/
public abstract class GraphicComponent {
/**
* 葉子及組合結(jié)點(diǎn)都實(shí)現(xiàn)的方法
*/
public abstract void draw();
/**
* 添加葉子結(jié)點(diǎn)方法
* 透明模式葉子結(jié)點(diǎn)不需要實(shí)現(xiàn)add方法, 默認(rèn)實(shí)現(xiàn)
* @param graphicComponent
*/
public void add(GraphicComponent graphicComponent) {
throw new UnsupportedOperationException("Object UnsupportedOperation add method");
}
/**
* 刪除葉子結(jié)點(diǎn)方法
* 透明模式葉子結(jié)點(diǎn)不需要實(shí)現(xiàn)remove方法, 默認(rèn)實(shí)現(xiàn)
* @param graphicComponent
*/
public void remove(GraphicComponent graphicComponent) {
throw new UnsupportedOperationException("Object UnsupportedOperation remove method");
}
/**
* 獲取葉子結(jié)點(diǎn)方法
* @param index 葉子結(jié)點(diǎn)索引
* @return
*/
public GraphicComponent getChild(int index) {
throw new UnsupportedOperationException("Object UnsupportedOperation getChild method");
}
}
/**
* @author chunyuliu
*/
public class LineLeaf extends GraphicComponent {
@Override
public void draw() {
System.out.println("LineLeaf draw");
}
}
/**
* @author chunyuliu
*/
public class RectangleLeaf extends GraphicComponent {
@Override
public void draw() {
System.out.println("RectangleLeaf draw");
}
}
/**
* @author chunyuliu
*/
public class TextLeaf extends GraphicComponent {
@Override
public void draw() {
System.out.println("TextLeaf draw");
}
}
/**
* @author chunyuliu
*/
public class PictureComposite extends GraphicComponent {
private List<GraphicComponent> childList = new ArrayList<GraphicComponent>();
@Override
public void add(GraphicComponent graphicComponent) {
childList.add(graphicComponent);
}
@Override
public void remove(GraphicComponent graphicComponent) {
childList.remove(graphicComponent);
}
@Override
public void draw() {
System.out.println("PictureComposite");
if (childList != null && childList.size() > 0) {
for (GraphicComponent graphicComponent : childList) {
graphicComponent.draw();
}
}
}
@Override
public GraphicComponent getChild(int index) {
if (childList == null || childList.size() <= index) {
return null;
}
return childList.get(index);
}
}
測(cè)試用例
/**
* @author chunyuliu
*/
public class CompositeTest {
@Test
public void graphicTest() {
// 子部件
GraphicComponent pictureComposite = new PictureComposite();
// 組合葉子部件
pictureComposite.add(new LineLeaf());
pictureComposite.add(new RectangleLeaf());
pictureComposite.add(new TextLeaf());
GraphicComponent subPictureComposite = new PictureComposite();
subPictureComposite.add(new LineLeaf());
subPictureComposite.add(new RectangleLeaf());
subPictureComposite.add(new TextLeaf());
pictureComposite.add(subPictureComposite);
pictureComposite.draw();
// 獲取葉子結(jié)點(diǎn)
System.out.println("RectangleLeaf: " + pictureComposite.getChild(1));
}
}