設計模式之Composite(組合)


Composite 定義:
將對象以樹形結構組織起來,以達成“部分-整體” 的層次結構,使得客戶端對單個對象和
組合對象的使用具有一致性.
Composite 比較容易理解,想到Composite 就應該想到樹形結構圖。組合體內這些對象都有
共同接口,當組合體一個對象的方法被調用執行時,Composite 將遍歷(Iterator)整個樹形
結構,尋找同樣包含這個方法的對象並實現調用執行。可以用牽一動百來形容。
所以Composite 模式使用到Iterator 模式,和Chain of Responsibility 模式類似。
Composite 好處:
1.使客戶端調用簡單,客戶端可以一致的使用組合結構或其中單個對象,用戶就不必關係自
己處理的是單個對象還是整個組合結構,這就簡化了客戶端代碼。
2.更容易在組合體內加入對象部件. 客戶端不必因爲加入了新的對象部件而更改代碼。
如何使用Composite?
首先定義一個接口或抽象類,這是設計模式通用方式了,其他設計模式對接口內部定義限制
不多,Composite 卻有個規定,那就是要在接口內部定義一個用於訪問和管理Composite 組
合體的對象們(或稱部件Component).
下面的代碼是以抽象類定義,一般儘量用接口interface,
public abstract class Equipment
{
private String name;
//網絡價格
public abstract double netPrice();
//折扣價格
public abstract double discountPrice();
//增加部件方法
public boolean add(Equipment equipment) { return false; }
//刪除部件方法
public boolean remove(Equipment equipment) { return false; }
//注意這裏,這裏就提供一種用於訪問組合體類的部件方法。
public Iterator iter() { return null; }
public Equipment(final String name) { this.name=name; }
}

抽象類Equipment 就是Component 定義,代表着組合體類的對象們,Equipment 中定義幾個
共同的方法。
public class Disk extends Equipment
{
public Disk(String name) { super(name); }
//定義Disk 網絡價格爲1
public double netPrice() { return 1.; }
//定義了disk 折扣價格是0.5 對摺。
public double discountPrice() { return .5; }
}
Disk 是組合體內的一個對象,或稱一個部件,這個部件是個單獨元素( Primitive)。
還有一種可能是,一個部件也是一個組合體,就是說這個部件下面還有'兒子',這是樹形結
構中通常的情況,應該比較容易理解。現在我們先要定義這個組合體:
abstract class CompositeEquipment extends Equipment
{
private int i=0;
//定義一個Vector 用來存放'兒子'
private Lsit equipment=new ArrayList();
public CompositeEquipment(String name) { super(name); }
public boolean add(Equipment equipment) {
this.equipment.add(equipment);
return true;
}
public double netPrice()
{
double netPrice=0.;
Iterator iter=equipment.iterator();
for(iter.hasNext())
netPrice+=((Equipment)iter.next()).netPrice();
return netPrice;
}
public double discountPrice()
{
double discountPrice=0.;
Iterator iter=equipment.iterator();
for(iter.hasNext())

discountPrice+=((Equipment)iter.next()).discountPrice();
return discountPrice;
}
//注意這裏,這裏就提供用於訪問自己組合體內的部件方法。
//上面dIsk 之所以沒有,是因爲Disk 是個單獨(Primitive)的元素.
public Iterator iter()
{
return equipment.iterator() ;
{
//重載Iterator 方法
public boolean hasNext() { return i //重載Iterator 方法
public Object next()
{
if(hasNext())
return equipment.elementAt(i++);
else
throw new NoSuchElementException();
}
}
上面CompositeEquipment 繼承了Equipment,同時爲自己裏面的對象們提供了外部訪問的方
法,重載了Iterator,Iterator 是Java 的Collection 的一個接口,是Iterator 模式的實現.
我們再看看CompositeEquipment 的兩個具體類:盤盒Chassis 和箱子Cabinet,箱子裏面可
以放很多東西,如底板,電源盒,硬盤盒等;盤盒裏面可以放一些小設備,如硬盤 軟驅等。
無疑這兩個都是屬於組合體性質的。
public class Chassis extends CompositeEquipment
{
public Chassis(String name) { super(name); }
public double netPrice() { return 1.+super.netPrice(); }
public double discountPrice()
{ return .5+super.discountPrice(); }
}
public class Cabinet extends CompositeEquipment
{
設計模式(Patterns in Java) -- http://www.jdon.com
36
public Cabinet(String name) { super(name); }
public double netPrice() { return 1.+super.netPrice(); }
public double discountPrice()
{ return .5+super.discountPrice(); }
}
至此我們完成了整個Composite 模式的架構。
我們可以看看客戶端調用Composote 代碼:
Cabinet cabinet=new Cabinet("Tower");
Chassis chassis=new Chassis("PC Chassis");
//將PC Chassis 裝到Tower 中 (將盤盒裝到箱子裏)
cabinet.add(chassis);
//將一個10GB 的硬盤裝到 PC Chassis (將硬盤裝到盤盒裏)
chassis.add(new Disk("10 GB"));
//調用 netPrice()方法;
System.out.println("netPrice="+cabinet.netPrice());
System.out.println("discountPrice="+cabinet.discountPrice());
上面調用的方法netPrice()或discountPrice(),實際上Composite 使用Iterator 遍歷了
整個樹形結構,尋找同樣包含這個方法的對象並實現調用執行.
Composite 是個很巧妙體現智慧的模式,在實際應用中,如果碰到樹形結構,我們就可以嘗
試是否可以使用這個模式。
以論壇爲例,一個版(forum)中有很多帖子(message),這些帖子有原始貼,有對原始貼的回
應貼,是個典型的樹形結構,那麼當然可以使用Composite 模式,那麼我們進入Jive 中看
看,是如何實現的.
Jive 解剖
在Jive 中 ForumThread 是ForumMessages 的容器container(組合體).也就是說,
ForumThread 類似我們上例中的 CompositeEquipment.它和messages 的關係如圖:
[thread]
|- [message]
|- [message]
|- [message]
|- [message]
|- [message]
我們在ForumThread 看到如下代碼:

public interface ForumThread {
....
public void addMessage(ForumMessage parentMessage,
ForumMessage newMessage)
throws UnauthorizedException;
public void deleteMessage(ForumMessage message)
throws UnauthorizedException;
public Iterator messages();
....
}
類似CompositeEquipment, 提供用於訪問自己組合體內的部件方法: 增加 刪除 遍歷.
結合我的其他模式中對Jive 的分析,我們已經基本大體理解了Jive 論壇體系的框架,如果
你之前不理解設計模式,而直接去看Jive 源代碼,你肯定無法看懂。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章