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

例子:
抽象組件:
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:[得到子節(jié)點(diǎn)]</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:[得到所有節(jié)點(diǎn)]</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:[是否葉節(jié)點(diǎn)]</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:[設(shè)置薪水]</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);
}

組件節(jié)點(diǎn):
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:[構(gòu)造方法]</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;
}

}

葉結(jié)點(diǎn):
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:[構(gòu)造方法]</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;
}

}

計(jì)算程序(和模式無關(guān)的):
package composite;

import java.util.Iterator;

public class CalcSalary


{

/** *//**
* <ul>
* <li>Description:[計(jì)算薪水方法]</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("上將編制內(nèi)的所有人員的薪水:" + CalcSalary.calcSalary(general));
System.out.println("上尉1編制內(nèi)的所有人員的薪水:" + CalcSalary.calcSalary(colonel1));
System.out.println("上校2編制內(nèi)的所有人員的薪水:" + CalcSalary.calcSalary(captain1));
}
}

要點(diǎn):
1. 組合模式以不遵守單一責(zé)任原則換取透明性,讓Client將組合和葉節(jié)點(diǎn)一視同仁。
2. 在實(shí)現(xiàn)組合模式時(shí),有很多設(shè)計(jì)上的折衷。要根據(jù)需求平衡透明性和安全性。
3. 有時(shí)候系統(tǒng)需要遍歷一個(gè)樹枝構(gòu)件的子構(gòu)件很多次,這時(shí)候可以把遍歷結(jié)果緩存起來。
4. 組合模式的實(shí)現(xiàn)中,可以讓子對象持有父對象的引用進(jìn)行反向追溯。
優(yōu)點(diǎn):
1. 組合模式可以很容易的增加新的構(gòu)件。
2. 使用組合模式可以使客戶端變的很容易設(shè)計(jì),因?yàn)榭蛻舳丝梢詫M合和葉節(jié)點(diǎn)一視同仁。
缺點(diǎn):
1. 使用組合模式后,控制樹枝構(gòu)件的類型不太容易。
2. 用繼承的方法來增加新的行為很困難。