组合模式 一、组合模式是什么? Compose objects into tree structure to represent part-whole hierarchies.Composite lets client treat individual objects and compositions of objects uniformly.
组合模式(Composite Design Pattern):将一组对象组织成树形结构,以表示一种“部分 - 整体”的层次结构。
也可以这么说,组合模式就是把容器与内容看成同一种对象,并将它们组合成树状结构,创造一种递归的形式。
比如文件和目录,虽然直观上是不同的对象,但是如果使用组合模式来实现它们的话,可以将文件和目录都看成是继承于同一种条目类,因此算是属于同一类对象。
其次,目录中又可以继续放文件和目录,形成了递归,最终是一种树状的层次结构。
二、为什么要用组合模式? 组合模式使用的场景有限,对数据格式比较严格:
尽管场景少,但是数据满足递归结构时,组合模式还是能发挥比较大的作用的:
组合模式可以让客户端以统一的方式访问数据节点,因为它们是同一种对象 
 
三、组合模式的结构是怎么样的? 组合模式包含的角色有以下几个:
抽象组件(Component):为树叶组件和复合组件提供一致性的抽象接口,并实现它们的默认行为 
树叶组件(Leaf):表示内容,不能再放其他抽象组件对象,在结构中属于最小对象 
复合组件(Composite):表示容器,可以放入其他抽象组件对象,包括树叶组件和复合组件 
 
示例程序结构:
抽象组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public  abstract  class  Entry  {    public  abstract  String getName () ;     public  abstract  int  getSize () ;     public  Entry add (Entry entry)  throws  FileTreatmentException {         throw  new  FileTreatmentException ();     }     public  void  printList ()  {         printList("" );     }     protected  abstract  void  printList (String prefix) ;     @Override      public  String toString ()  {         return  getName() + " ("  + getSize() + ")" ;     } } 
树叶组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public  class  File  extends  Entry  {    private  String name;     private  int  size;     public  File (String name, int  size)  {         this .name = name;         this .size = size;     }     @Override      public  String getName ()  {         return  name;     }     @Override      public  int  getSize ()  {         return  size;     }     @Override      protected  void  printList (String prefix)  {         System.out.println(prefix + "/"  + this );     } } 
复合组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public  class  Directory  extends  Entry  {    private  String name;     private  List<Entry> directory = new  ArrayList <>();     public  Directory (String name)  {         this .name = name;     }     @Override      public  String getName ()  {         return  name;     }     @Override      public  int  getSize ()  {         int  size  =  0 ;         for  (Entry entry : directory) {             size += entry.getSize();         }         return  size;     }     @Override      public  Entry add (Entry entry)  throws  FileTreatmentException {         directory.add(entry);         return  this ;     }     @Override      protected  void  printList (String prefix)  {         System.out.println(prefix + "/"  + this );         for  (Entry entry : directory) {             entry.printList(prefix + "/"  + name);         }     } } 
客户端调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public  class  MainTest  {    public  static  void  main (String[] args)  {         System.out.println("Making root entries..." );         Directory  rootDir  =  new  Directory ("root" );         Directory  binDir  =  new  Directory ("bin" );         Directory  tmpDir  =  new  Directory ("tmp" );         Directory  usrDir  =  new  Directory ("usr" );         rootDir.add(binDir);         rootDir.add(tmpDir);         rootDir.add(usrDir);         binDir.add(new  File ("vi" , 10000 ));         binDir.add(new  File ("latex" , 20000 ));         rootDir.printList();         System.out.println("" );         System.out.println("Making user entries..." );         Directory  yuki  =  new  Directory ("yuki" );         Directory  hanako  =  new  Directory ("hanako" );         Directory  tomura  =  new  Directory ("tomura" );                  usrDir.add(yuki);         usrDir.add(hanako);         usrDir.add(tomura);         yuki.add(new  File ("diary.html" , 100 ));         yuki.add(new  File ("Composite.java" , 300 ));         hanako.add(new  File ("memo.text" , 400 ));         tomura.add(new  File ("game.doc" , 500 ));         tomura.add(new  File ("junk.maik" , 600 ));         rootDir.printList();     }      } 
四、组合模式有什么优缺点? 优点:
可以统一地对待内容组件和复合组件,使用简单 
添加新的组件,不会影响客户端调用,满足“开闭原则” 
 
缺点: