組合模式( Composite Pattern)


參考文檔:http://blog.csdn.net/ai92/article/details/298336

 

定義:

組合多個對象形成樹形結構以表示“整體-部分”的結構層次。


設計動機:


這幅圖片我們都可以看做是一個文件結構,對於這樣的結構我們稱之為樹形結構。在數據結構中我們了解到可以通過調用某個方法來遍歷整個樹,當我們找到某個葉子節點后,就可以對葉子節點進行相關的操作。我們可以將這顆樹理解成一個大的容器,容器里面包含很多的成員對象,這些成員對象即可是容器對象也可以是葉子對象。但是由於容器對象和葉子對象在功能上面的區別,使得我們在使用的過程中必須要區分容器對象和葉子對象,但是這樣就會給客戶帶來不必要的麻煩,作為客戶而已,它始終希望能夠一致的對待容器對象和葉子對象。這就是組合模式的設計動機:組合模式定義了如何將容器對象和葉子對象進行遞歸組合,使得客戶在使用的過程中無須進行區分,可以對他們進行一致的處理。


模式實現:

  • Component:抽象構件角色。它為組合中的對象聲明接口,也可以為共有接口實現缺省行為
  • Leaf:樹葉構件角色。在組合中表示葉節點對象——沒有子節點,實現抽象構件角色聲明的接口。

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

     

     一種方式是在Component里面聲明所有的用來管理子類對象的方法,以達到Component接口的最大化(如下圖所示)。目的就是為了使客戶看來在接口層次上樹葉和分支沒有區別——透明性。但樹葉是不存在子類的,因此Component聲明的一些方法對於樹葉來說是不適用的。這樣也就帶來了一些安全性問題。




      另一種方式就是只在Composite里面聲明所有的用來管理子類對象的方法(如下圖所示)。這樣就避免了上一種方式的安全性問題,但是由於葉子和分支有不同的接口,所以又失去了透明性。

  《設計模式》一書認為:在這一模式中,相對於安全性,我們比較強調透明性。對於第一種方式中葉子節點內不需要的方法可以使用空處理或者異常報告的方式來解決。


優點:

      1、可以清楚地定義分層次的復雜對象,表示對象的全部或部分層次,使得增加新構件也更容易。

      2、客戶端調用簡單,客戶端可以一致的使用組合結構或其中單個對象。

      3、定義了包含葉子對象和容器對象的類層次結構,葉子對象可以被組合成更復雜的容器對象,而這個容器對象又可以被組合,這樣不斷遞歸下去,可以形成復雜的樹形結構。

      4、更容易在組合體內加入對象構件,客戶端不必因為加入了新的對象構件而更改原有代碼。

 

舉個栗子:

 定義抽象角色

abstract class File{
    public abstract void addChild(File f);
    public abstract void delChild(File f);
    public abstract void scan();
}

 

 定義葉子實現

class ImgFile extends File{
    @Override
    public void addChild(File f) {
    }
    @Override
    public void delChild(File f) {
    }
    @Override
    public void scan() {
        System.out.println("im an img");
    }
}

 定義葉子實現

    class VideoFile extends File{  
        @Override  
        public void addChild(File f) {  
        }  
        @Override  
        public void delChild(File f) {  
        }  
        @Override  
        public void scan() {  
            System.out.println("im a video");  
        }  
    }  

定義樹枝實現

    class Folder extends File{  
        List<File> files=new ArrayList<File>();  
        @Override  
        public void addChild(File f) {  
            files.add(f);  
        }  
        @Override  
        public void delChild(File f) {  
            files.remove(f);          
        }  
        @Override  
        public void scan() {  
            System.out.println("im folder,i have some files :");  
            for (File f : files) {  
                f.scan();  
            }  
        }  
    }  

客戶端調用

    public static void main(String[] args) {  
          File c=new Folder();  
          File windows=new  Folder();  
          windows.addChild(new ImgFile());  
          c.addChild(windows);  
          c.scan();  
        }  

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: