設計模式之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<equipment.size(); }
  //重載Iterator方法

   public Object next()
  
{
    
if(hasNext())
      
return equipment.elementAt(i++);
    
else
       
throw new NoSuchElementException();
  
}
  


}

上面CompositeEquipment繼承了Equipment,同時爲自己裏面的物件們提供了外部訪問的方法,重載了Iterator,IteratorJavaCollection的一個介面,是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 ForumThreadForumMessages的容器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源代碼,你肯定無法看懂。

:)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值