組合模式:允許你將對象組合成樹型結構來表現“整體/部分”層次結構。組合能讓客戶以一致的方式處理個別對象以及對象組合.
Composite模式涉及的是一組對象,其中有些對象可能含有其他的對象;因此,有些對象可能代表一個對象群組,而其他的則是單個對象,即葉子。利用Composite模式建模包含兩個重要的建模概念。其中一個重要的思想是所設計的群組即能包含單個個體,還要能包含其他群組(一個常見的錯誤是所設計的群組只能包含葉子)。另一個重要的概念是要定義出單個對象和對象組合的公共特性。結合這兩個概念,我們可以定義即適合群組又適合單個個體的通用類型,然后將群組建模成具有這種類型的對象的集合。
Composite模式的設計意圖在于:讓用戶能夠用統一的接口處理單個對象以及對象組合.
組合模式的組成部份:
1.抽象組件
2.組件節點
3.葉節點
組合模式的各組成部份之間的關系:

例子:
抽象組件:
package composite;

import java.util.Iterator;


/** *//**
* <ul>
* <li>Title:[MilitaryPerson]</li>
* <li>Description: [軍人抽象組件]</li>
* <li>Copyright 2009 Upengs Co., Ltd.</li>
* <li>All right reserved.</li>
* <li>Created by [Huyvanpull] [2011-8-2]</li>
* <li>Midified by [modifier] [modified time]</li>
* </ul>
*
* @version 1.0
*/
public interface MilitaryPerson


{

/** *//**
* <ul>
* <li>Description:[添加組件]</li>
* <li>Created by [Huyvanpull] [2011-8-2]</li>
* <li>Midified by [modifier] [modified time]</li>
* </ul>
*
* @param person
*/
public void add(MilitaryPerson person);

/** *//**
* <ul>
* <li>Description:[刪除組件]</li>
* <li>Created by [Huyvanpull] [2011-8-2]</li>
* <li>Midified by [modifier] [modified time]</li>
* </ul>
*
* @param person
*/
public void remove(MilitaryPerson person);

/** *//**
* <ul>
* <li>Description:[得到子節點]</li>
* <li>Created by [Huyvanpull] [2011-8-2]</li>
* <li>Midified by [modifier] [modified time]</li>
* </ul>
*
* @param index
* @return
*/
public MilitaryPerson getChild(int index);

/** *//**
* <ul>
* <li>Description:[得到所有節點]</li>
* <li>Created by [Huyvanpull] [2011-8-2]</li>
* <li>Midified by [modifier] [modified time]</li>
* </ul>
*
* @return
*/
public Iterator<MilitaryPerson> getAllChildren();

/** *//**
* <ul>
* <li>Description:[是否葉節點]</li>
* <li>Created by [Huyvanpull] [2011-8-2]</li>
* <li>Midified by [modifier] [modified time]</li>
* </ul>
*
* @return
*/
public boolean isLeaf();

/** *//**
* <ul>
* <li>Description:[得到薪水]</li>
* <li>Created by [Huyvanpull] [2011-8-2]</li>
* <li>Midified by [modifier] [modified time]</li>
* </ul>
*
* @return
*/
public double getSalary();

/** *//**
* <ul>
* <li>Description:[設置薪水]</li>
* <li>Created by [Huyvanpull] [2011-8-2]</li>
* <li>Midified by [modifier] [modified time]</li>
* </ul>
*
* @param salary
* @return
*/
public double setSalary(double salary);
}

組件節點:
package composite;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/** *//**
* <ul>
* <li>Title:[MilitaryOfficer]</li>
* <li>Description: [軍官]</li>
* <li>Copyright 2009 Upengs Co., Ltd.</li>
* <li>All right reserved.</li>
* <li>Created by [Huyvanpull] [2011-8-2]</li>
* <li>Midified by [modifier] [modified time]</li>
* </ul>
* @version 1.0
*/
public class MilitaryOfficer implements MilitaryPerson


{

/** *//** 姓名 */
public String name;

/** *//** 薪水 */
public double salary;

/** *//** 組件容器 */
private List<MilitaryPerson> militaryPersonLst;

/** *//**
*<ul>
*<li>Description:[構造方法]</li>
*<ul>
* @param name
* @param salary
*/
public MilitaryOfficer(String name, double salary)

{
this.name = name;
this.salary = salary;
this.militaryPersonLst = new ArrayList<MilitaryPerson>();
}

/**//* (non-Javadoc)
* @see composite.MilitaryPerson#add(composite.MilitaryPerson)
*/
public void add(MilitaryPerson person)

{
this.militaryPersonLst.add(person);
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#getAllChildren()
*/
public Iterator<MilitaryPerson> getAllChildren()

{
return this.militaryPersonLst.iterator();
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#getChild(int)
*/
public MilitaryPerson getChild(int index)

{
return this.militaryPersonLst.get(index);
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#getSalary()
*/
public double getSalary()

{
return salary;
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#isLeaf()
*/
public boolean isLeaf()

{
return false;
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#remove(composite.MilitaryPerson)
*/
public void remove(MilitaryPerson person)

{
this.militaryPersonLst.remove(person);
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#setSalary(double)
*/
public double setSalary(double salary)

{
return salary;
}

}

葉結點:
package composite;

import java.util.Iterator;


/** *//**
* <ul>
* <li>Title:[MilitarySoldier]</li>
* <li>Description: [士兵]</li>
* <li>Copyright 2009 Upengs Co., Ltd.</li>
* <li>All right reserved.</li>
* <li>Created by [Huyvanpull] [2011-8-2]</li>
* <li>Midified by [modifier] [modified time]</li>
* </ul>
* @version 1.0
*/
public class MilitarySoldier implements MilitaryPerson


{

/** *//** 姓名 */
public String name;

/** *//** 薪水 */
public double salary;

/** *//**
*<ul>
*<li>Description:[構造方法]</li>
*<ul>
* @param name
* @param salary
*/
public MilitarySoldier(String name, double salary)

{
this.name = name;
this.salary = salary;
}

/**//* (non-Javadoc)
* @see composite.MilitaryPerson#add(composite.MilitaryPerson)
*/
public void add(MilitaryPerson person)

{
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#getAllChildren()
*/
public Iterator<MilitaryPerson> getAllChildren()

{
return null;
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#getChild(int)
*/
public MilitaryPerson getChild(int index)

{
return null;
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#getSalary()
*/
public double getSalary()

{
return salary;
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#isLeaf()
*/
public boolean isLeaf()

{
return true;
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#remove(composite.MilitaryPerson)
*/
public void remove(MilitaryPerson person)

{
}


/**//* (non-Javadoc)
* @see composite.MilitaryPerson#setSalary(double)
*/
public double setSalary(double salary)

{
return salary;
}

}

計算程序(和模式無關的):
package composite;

import java.util.Iterator;

public class CalcSalary


{

/** *//**
* <ul>
* <li>Description:[計算薪水方法]</li>
* <li>Created by [Huyvanpull] [2011-8-2]</li>
* <li>Midified by [modifier] [modified time]</li>
* </ul>
* @param person
* @return
*/
public static double calcSalary(MilitaryPerson person)

{
double sumSalary = person.getSalary();
if (!person.isLeaf())

{
Iterator<MilitaryPerson> iterator = person.getAllChildren();
while (iterator.hasNext())

{
MilitaryPerson militaryPerson = iterator.next();
sumSalary += militaryPerson.getSalary();
}
}
return sumSalary;
}
}

測試:
package composite;

public class Test


{
public static void main(String[] args)

{
// 上將
MilitaryPerson general = new MilitaryOfficer("上將", 100000);
// 上校
MilitaryPerson colonel1 = new MilitaryOfficer("上校1", 80000);
MilitaryPerson colonel2 = new MilitaryOfficer("上校2", 80000);
general.add(colonel1);
general.add(colonel2);
// 上尉
MilitaryPerson captain1 = new MilitaryOfficer("上尉1", 60000);
MilitaryPerson captain2 = new MilitaryOfficer("上尉2", 60000);
colonel1.add(captain1);
colonel1.add(captain2);
MilitaryPerson captain3 = new MilitaryOfficer("上尉3", 60000);
MilitaryPerson captain4 = new MilitaryOfficer("上尉4", 60000);
colonel2.add(captain3);
colonel2.add(captain4);
// 士兵
MilitarySoldier airman1 = new MilitarySoldier("士兵", 10000);
MilitarySoldier airman2 = new MilitarySoldier("士兵", 10000);
MilitarySoldier airman3 = new MilitarySoldier("士兵", 10000);
captain1.add(airman1);
captain1.add(airman2);
captain1.add(airman3);
MilitarySoldier airman4 = new MilitarySoldier("士兵", 10000);
MilitarySoldier airman5 = new MilitarySoldier("士兵", 10000);
MilitarySoldier airman6 = new MilitarySoldier("士兵", 10000);
captain2.add(airman4);
captain2.add(airman5);
captain2.add(airman6);
MilitarySoldier airman7 = new MilitarySoldier("士兵", 10000);
MilitarySoldier airman8 = new MilitarySoldier("士兵", 10000);
MilitarySoldier airman9 = new MilitarySoldier("士兵", 10000);
captain3.add(airman7);
captain3.add(airman8);
captain3.add(airman9);
MilitarySoldier airman10 = new MilitarySoldier("士兵", 10000);
MilitarySoldier airman11 = new MilitarySoldier("士兵", 10000);
MilitarySoldier airman12 = new MilitarySoldier("士兵", 10000);
captain4.add(airman10);
captain4.add(airman11);
captain4.add(airman12);
System.out.println("上將編制內的所有人員的薪水:" + CalcSalary.calcSalary(general));
System.out.println("上尉1編制內的所有人員的薪水:" + CalcSalary.calcSalary(colonel1));
System.out.println("上校2編制內的所有人員的薪水:" + CalcSalary.calcSalary(captain1));
}
}

要點:
1. 組合模式以不遵守單一責任原則換取透明性,讓Client將組合和葉節點一視同仁。
2. 在實現組合模式時,有很多設計上的折衷。要根據需求平衡透明性和安全性。
3. 有時候系統需要遍歷一個樹枝構件的子構件很多次,這時候可以把遍歷結果緩存起來。
4. 組合模式的實現中,可以讓子對象持有父對象的引用進行反向追溯。
優點:
1. 組合模式可以很容易的增加新的構件。
2. 使用組合模式可以使客戶端變的很容易設計,因為客戶端可以對組合和葉節點一視同仁。
缺點:
1. 使用組合模式后,控制樹枝構件的類型不太容易。
2. 用繼承的方法來增加新的行為很困難。