劍心博客

          Just for java

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            1 隨筆 :: 29 文章 :: 1 評(píng)論 :: 0 Trackbacks

          設(shè)計(jì)模式之Composite(組合)

          板橋里人 http://www.jdon.com 2002/04/27(轉(zhuǎn)載請(qǐng)保留)

          Composite模式定義:
          將對(duì)象以樹(shù)形結(jié)構(gòu)組織起來(lái),以達(dá)成“部分-整體” 的層次結(jié)構(gòu),使得客戶端對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性.

          Composite比較容易理解,想到Composite就應(yīng)該想到樹(shù)形結(jié)構(gòu)圖。組合體內(nèi)這些對(duì)象都有共同接口,當(dāng)組合體一個(gè)對(duì)象的方法被調(diào)用執(zhí)行時(shí),Composite將遍歷(Iterator)整個(gè)樹(shù)形結(jié)構(gòu),尋找同樣包含這個(gè)方法的對(duì)象并實(shí)現(xiàn)調(diào)用執(zhí)行。可以用牽一動(dòng)百來(lái)形容。

          所以Composite模式使用到Iterator模式,和Chain of Responsibility模式類似。

          Composite好處:
          1.使客戶端調(diào)用簡(jiǎn)單,客戶端可以一致的使用組合結(jié)構(gòu)或其中單個(gè)對(duì)象,用戶就不必關(guān)系自己處理的是單個(gè)對(duì)象還是整個(gè)組合結(jié)構(gòu),這就簡(jiǎn)化了客戶端代碼。
          2.更容易在組合體內(nèi)加入對(duì)象部件. 客戶端不必因?yàn)榧尤肓诵碌膶?duì)象部件而更改代碼。

          如何使用Composite?
          首先定義一個(gè)接口或抽象類,這是設(shè)計(jì)模式通用方式了,其他設(shè)計(jì)模式對(duì)接口內(nèi)部定義限制不多,Composite卻有個(gè)規(guī)定,那就是要在接口內(nèi)部定義一個(gè)用于訪問(wèn)和管理Composite組合體的對(duì)象們(或稱部件Component).

          下面的代碼是以抽象類定義,一般盡量用接口interface,

          public abstract class Equipment
          {
            private String name;
            //實(shí)價(jià)
            public abstract double netPrice();
            //折扣價(jià)格
            public abstract double discountPrice();
            //增加部件方法  
            public boolean add(Equipment equipment) { return false; }
            //刪除部件方法
            public boolean remove(Equipment equipment) { return false; }
            //注意這里,這里就提供一種用于訪問(wèn)組合體類的部件方法。
            public Iterator iter() { return null; }
            
            public Equipment(final String name) { this.name=name; }
          }

          抽象類Equipment就是Component定義,代表著組合體類的對(duì)象們,Equipment中定義幾個(gè)共同的方法。

          public class Disk extends Equipment
          {
            public Disk(String name) { super(name); }
            //定義Disk實(shí)價(jià)為1
            public double netPrice() { return 1.; }
            //定義了disk折扣價(jià)格是0.5 對(duì)折。
            public double discountPrice() { return .5; }
          }

          Disk是組合體內(nèi)的一個(gè)對(duì)象,或稱一個(gè)部件,這個(gè)部件是個(gè)單獨(dú)元素( Primitive)。
          還有一種可能是,一個(gè)部件也是一個(gè)組合體,就是說(shuō)這個(gè)部件下面還有'兒子',這是樹(shù)形結(jié)構(gòu)中通常的情況,應(yīng)該比較容易理解。現(xiàn)在我們先要定義這個(gè)組合體:

          abstract class CompositeEquipment extends Equipment
          {
            private int i=0;
            //定義一個(gè)Vector 用來(lái)存放'兒子'
            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;
            }
            

            //注意這里,這里就提供用于訪問(wèn)自己組合體內(nèi)的部件方法。
            //上面dIsk 之所以沒(méi)有,是因?yàn)镈isk是個(gè)單獨(dú)(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,同時(shí)為自己里面的對(duì)象們提供了外部訪問(wèn)的方法,重載了Iterator,Iterator是Java的Collection的一個(gè)接口,是Iterator模式的實(shí)現(xiàn).

          我們?cè)倏纯碈ompositeEquipment的兩個(gè)具體類:盤(pán)盒Chassis和箱子Cabinet,箱子里面可以放很多東西,如底板,電源盒,硬盤(pán)盒等;盤(pán)盒里面可以放一些小設(shè)備,如硬盤(pán) 軟驅(qū)等。無(wú)疑這兩個(gè)都是屬于組合體性質(zhì)的。

          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(); }
          }

          至此我們完成了整個(gè)Composite模式的架構(gòu)。

          我們可以看看客戶端調(diào)用Composote代碼:

          Cabinet cabinet=new Cabinet("Tower");

          Chassis chassis=new Chassis("PC Chassis");
          //將PC Chassis裝到Tower中 (將盤(pán)盒裝到箱子里)
          cabinet.add(chassis);
          //將一個(gè)10GB的硬盤(pán)裝到 PC Chassis (將硬盤(pán)裝到盤(pán)盒里)
          chassis.add(new Disk("10 GB"));

          //調(diào)用 netPrice()方法;
          System.out.println("netPrice="+cabinet.netPrice());
          System.out.println("discountPrice="+cabinet.discountPrice());

          上面調(diào)用的方法netPrice()或discountPrice(),實(shí)際上Composite使用Iterator遍歷了整個(gè)樹(shù)形結(jié)構(gòu),尋找同樣包含這個(gè)方法的對(duì)象并實(shí)現(xiàn)調(diào)用執(zhí)行.

          Composite是個(gè)很巧妙體現(xiàn)智慧的模式,在實(shí)際應(yīng)用中,如果碰到樹(shù)形結(jié)構(gòu),我們就可以嘗試是否可以使用這個(gè)模式。

          以論壇為例,一個(gè)版(forum)中有很多帖子(message),這些帖子有原始貼,有對(duì)原始貼的回應(yīng)貼,是個(gè)典型的樹(shù)形結(jié)構(gòu),那么當(dāng)然可以使用Composite模式,那么我們進(jìn)入Jive中看看,是如何實(shí)現(xiàn)的.

          Jive解剖
          在Jive中 ForumThread是ForumMessages的容器container(組合體).也就是說(shuō),F(xiàn)orumThread類似我們上例中的 CompositeEquipment.它和messages的關(guān)系如圖:
          [thread]
             |- [message]
             |- [message]
                |- [message]
                |- [message]
                   |- [message]

          我們?cè)贔orumThread看到如下代碼:

          public interface ForumThread {
             ....
             public void addMessage(ForumMessage parentMessage, ForumMessage newMessage)
                   throws UnauthorizedException;

             public void deleteMessage(ForumMessage message)
                   throws UnauthorizedException;

            
             public Iterator messages();
                ....

          }

          類似CompositeEquipment, 提供用于訪問(wèn)自己組合體內(nèi)的部件方法: 增加 刪除 遍歷.

          結(jié)合我的其他模式中對(duì)Jive的分析,我們已經(jīng)基本大體理解了Jive論壇體系的框架,如果你之前不理解設(shè)計(jì)模式,而直接去看Jive源代碼,你肯定無(wú)法看懂。

          參考文章:

          Composite模式和樹(shù)形結(jié)構(gòu)的討論

          posted on 2006-12-11 19:47 powerwind 閱讀(168) 評(píng)論(0)  編輯  收藏 所屬分類: 轉(zhuǎn)來(lái)好帖java設(shè)計(jì)模式
          主站蜘蛛池模板: 枣阳市| 青阳县| 镇宁| 新田县| 砀山县| 香港| 文化| 海盐县| 图木舒克市| 神农架林区| 和顺县| 广饶县| 名山县| 简阳市| 永福县| 永登县| 万源市| 屏南县| 金坛市| 北川| 荣昌县| 英山县| 百色市| 康平县| 大荔县| 沁阳市| 石嘴山市| 清水县| 隆昌县| 昌平区| 阜南县| 沐川县| 富蕴县| 招远市| 黄平县| 子长县| 都匀市| 岚皋县| 通道| 江华| 墨江|