??? 組合模式:將對象以樹形結構組織起來,以達成“部分-整體” 的層次結構,使得客戶端對單個對象和組合對象的使用具有一致性.
??? 適用環境:

u?????? 你想表示對象的部分-整體層次結構。

u?????? 你希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象。

Composite好處
:
1.使客戶端調用簡單,客戶端可以一致的使用組合結構或其中單個對象,用戶就不必關系自己處理的是單個對象還是整個組合結構,這就簡化了客戶端代碼。
2.更容易在組合體內加入對象部件. 客戶端不必因為加入了新的對象部件而更改代碼。

組合模式的組成

1)???????? 抽象構件角色Component:它為組合中的對象聲明接口,也可以為共有接口實現缺省行為。

2)?????? 樹葉構件角色Leaf:在組合中表示葉節點對象——沒有子節點,實現抽象構件角色聲明的接口。

3)?????? 樹枝構件角色Composite:在組合中表示分支節點對象——有子節點,實現抽象構件角色聲明的接口;存儲子部件。

下圖為組合模式的類圖表示。
comp1.bmp
三、安全性與透明性

組合模式中必須提供對子對象的管理方法,不然無法完成對子對象的添加刪除等等操作,也就失去了靈活性和擴展性。但是管理方法是在Component中就聲明還是在Composite中聲明呢?

一種方式是在Component里面聲明所有的用來管理子類對象的方法,以達到Component接口的最大化(如下圖所示)。目的就是為了使客戶看來在接口層次上樹葉和分支沒有區別——透明性。但樹葉是不存在子類的,因此Component聲明的一些方法對于樹葉來說是不適用的。這樣也就帶來了一些安全性問題。
?? 另一種方式就是只在Composite里面聲明所有的用來管理子類對象的方法(如下圖所示)。這樣就避免了上一種方式的安全性問題,但是由于葉子和分支有不同的接口,所以又失去了透明性。
??《設計模式》一書認為:在這一模式中,相對于安全性,我們比較強調透明性。對于第一種方式中葉子節點內不需要的方法可以使用空處理或者異常報告的方式來解決。
如何使用Composite?
首先定義一個接口或抽象類Component

package?composite;
import?java.util.Iterator;
public?abstract?class?Equipment{
????
//名稱
????private?String?name;
????
//價格
????public?abstract?double?netPrice();
????
//增加一個部件
????public?boolean?add(Equipment?equ){
????????
return?false;
????}

????
//刪除一個部件
????public?boolean?remove(Equipment?equ){
????????
return?false;
????}

????
//迭代指針
????public?Iterator?iter(){
????????
return?null;
????}

????
//構造方法
????public?Equipment(String?name){
????????
this.name=name;
????}

}
Disk類Leaf角色
package?composite;
public?class?Disk?extends?Equipment{
????
//構造方法
????public?Disk(String?name){
????????
super(name);
????}

????
//定價
????public?double?netPrice(){
????????
return?1.2;
????}

}
CompositeEquipment 類Composite角色
package?composite;
import?java.util.*;
public?abstract?class?CompositeEquipment??extends?Equipment{
????
private?List?equipment=new?ArrayList();
????
public?CompositeEquipment(String?name){
????????
super(name);
????}

????
public?boolean?add(Equipment?equ){
????????equipment.add(equ);
????????
return?true;
????}

????
public?boolean?remove(Equipment?equ){
????????equipment.remove(equ);
????????
return?true;
????}

????
????
public?Iterator?iter(){
????????
return?equipment.iterator();
????}

????
????
public?double?netPrice(){
????????
double?netprice=0;
????????Iterator?it
=equipment.iterator();
????????
while(it.hasNext()){
????????????netprice
+=((Equipment)it.next()).netPrice();
????????}

????????
return?netprice;
????}

????
}
CompositeEquipment的兩個具體類
package?composite;
public?class?Chassis?extends?CompositeEquipment{
????
public?Chassis(String?name){
????????
super(name);
????}

????
????
public?double?netPrice(){
????????
return?3.0+super.netPrice();
????}

????
}
package?composite;
public?class?Cabinet?extends?CompositeEquipment{
????
public?Cabinet(String?name){
????????
super(name);
????}

????
????
public?double?netPrice(){
????????
return?3.0+super.netPrice();
????}

????
}
運行類
package?composite;
public?class?Composite{
????
public?static?void?main(String[]?args){
????????Cabinet?cabinet
=new?Cabinet("Tomer");
????????Chassis?chassis
=new?Chassis("PC?chassis");
????????
????????cabinet.add(chassis);
????????chassis.add(
new?Disk("120Gb"));
????????
????????System.out.println(cabinet.netPrice());
????}

}
運行結果如:
7.2
Press any key to continue...


參考資料:http://blog.csdn.net/ai92/archive/2005/02/23/298336.aspx
?http://www.lvjiyong.com/books/DesignPatterns/21.html
http://www.jdon.com/designpatterns/composite.htm