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<equipment.size(); } //重載Iterator方法 public Object next() { if(hasNext()) return equipment.elementAt(i++); else throw new NoSuchElementException(); }
}
|
上面CompositeEquipment繼承了Equipment,同時為自己里面的對象們提供了外部訪問的方法,重載了Iterator,Iterator是Java的Collection的一個接口,是Iterator模式的實現.一般沒必要重載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 { 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, 提供用于訪問自己組合體內的部件方法: 增加 刪除 遍歷.
--------------------------------------
??? Composite模式的意圖是“將對象組合成樹形結構表示‘整體-部分’的層次結構。Composite使得用戶對單個對象和組合對象的使用更具有一致性”。
??? 在Word中我們經常會將一些圖元進行“組合”,組合以后的圖形還可以向簡單圖元那樣進行移動、變形等等操作;除此以外,在Word中,我們對于一個字符、一個詞組、一句話、一個段落,甚至是整篇文章的操作是相同的,我們都可以進行剪切、復制,進行字體與大小的調整,進行顏色的變換。這些例子都是Composite模式的實例,我們將簡單的元素組合成復雜的元素,然后還可以像操作簡單元素那樣操作組合元素。
??? Composite模式將子元素組織成樹型,實際上,組織成圖型也沒有問題。用戶總是喜歡組合簡單元素,一方面,用戶可以通過這樣的組合來進行抽象,另一方面,用戶可以通過組合化簡繁瑣的操作。Composite模式在各種可視化編輯軟件中應用得最為廣泛。
??? 另一使用Composite的經典例子是Java的Swing系統。所有的Swing組件都是繼承自一個叫做JComponent的接口,因此,我們對一個JFrame的操作和對一個JButton的操作是一樣的。這同時也使得,JFrame在管理自己的子元素時,它不需要知道他們是一個JButton還是一個JPanel,對它來說,這只是一個JComponent。
??? 實現Composite模式的關鍵是良好設計的接口,人們應該對可能的元素(簡單的、組合的)進行分析,并設計出通用的操作。盡可能的保證接口操作對所有元素都是有意義的,否則就應該將那些只對部分元素有意義的操作下放到子類中。

posted on 2006-07-31 17:16
保爾任 閱讀(795)
評論(0) 編輯 收藏 所屬分類:
Design Patten