设计模式-组合模式(Composite Pattern)
本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/
前置技能:认识数据结构中的树形结构。
组合模式简介
组合模式是将对象组合成树形结构以表示“部分-整体”的层次结构,每一个节点可以是叶子节点也可以使包含一堆子节点的中间节点,而且所有的节点都有同样的接口,用户在使用的时候无需区分节点类型,也就是可以将整个结构的任意部分当成“整体”来处理,这就是组合模式带来的方便。
组合模式的定义和基本结构
定义:将对象组合成树形结构以表示“部分-整体”的层次结构,并且为不同类型的节点提供完全相同的接口,让用户可以将整个结构的任意部分当成“整体”来处理。
一张来自《Head First》的结构图
Client:用户类,通过Component操作组合模式中的节点。
Component:组合模式中树状结构的每一个节点都要实现的接口,提供基本操作。
Leaf:树状结构中的叶子节点。
Composite:树状结构中的非叶子结点。
注意:我们可以看到,Component接口中有很多方法只适合于Composite而不适合Leaf,所以在Leaf中我们需要做好相应的处理工作,来让使用者感受不到差异的同时又不产生运行错误或者逻辑错误,如leaf没有孩子,我们可以让getChild方法直接抛出异常,或者返回null,一切都要结合实际使用背景来设计合适的处理逻辑。
一个简单的实例(java)
我们就实现一个纯的结构吧,每一个节点都包含一个字符串,Composite节点包含子节点,每个节点都可以打印自己的字符串,也可以一并打印自己所有子节点的字符串。
首先我们要定义一个Component。
1 public abstract class Component{ 2 private String s; 3 public Component(String s){ 4 this.s=s; 5 } 6 public String getString() { 7 return s; 8 } 9 public void print() { 10 System.out.println(getString()); 11 } 12 public abstract void printAll(); 13 public abstract void remove(Component s); 14 public void add(Component s) { 15 new UnsupportedOperationException(); 16 } 17 public Component getChild(int i) { 18 new UnsupportedOperationException(); 19 return null; 20 } 21 }
然后我们实现MyComposite类,这里储存子节点借用了ArrayList。
1 import java.util.ArrayList; 2 public class MyComposite extends Component { 3 private ArrayList<Component> list; 4 public MyComposite(String s) { 5 super(s); 6 list=new ArrayList<Component>(); 7 } 8 @Override 9 public void printAll() { 10 System.out.println(getString()+"---------------"+"start"); 11 for(Component c:list) 12 c.printAll(); 13 System.out.println(getString()+"---------------"+"end"); 14 } 15 @Override 16 public void add(Component s) { 17 list.add(s); 18 } 19 @Override 20 public void remove(Component s) { 21 if(!list.remove(s)){ 22 for(Component c:list) 23 c.remove(s); 24 } 25 } 26 @Override 27 public Component getChild(int i) { 28 if(i<list.size()) 29 return list.get(i); 30 new IndexOutOfBoundsException(); 31 return null; 32 } 33 }
然后实现MyLeaf,这个相对简单。
1 public class MyLeaf extends Component { 2 public MyLeaf(String s) { 3 super(s); 4 } 5 public void printAll() { 6 print(); 7 } 8 @Override 9 public void remove(Component s) { 10 } 11 }
然后是测试类。
1 public class Test { 2 public static void main(String[] args) { 3 Component root=new MyComposite("1-root"); 4 root.add(new MyLeaf("2-1-Leaf")); 5 root.add(new MyComposite("2-2-Composite")); 6 Component r=new MyComposite("3-1-composite"); 7 root.getChild(1).add(r); 8 root.getChild(1).add(new MyLeaf("3-2-leaf")); 9 root.getChild(1).add(new MyLeaf("3-3-leaf")); 10 11 root.getChild(1).getChild(0).add(new MyLeaf("4-1-leaf")); 12 Component r2=new MyLeaf("4-2-leaf"); 13 root.getChild(1).getChild(0).add(r2); 14 root.getChild(1).getChild(0).add(new MyLeaf("4-3-leaf")); 15 root.getChild(1).getChild(0).add(new MyLeaf("4-4-leaf")); 16 root.printAll(); 17 System.out.print("**************************************"); 18 root.print(); 19 root.remove(r2); 20 root.printAll(); 21 System.out.print("**************************************"); 22 root.print(); 23 root.remove(r); 24 root.printAll(); 25 System.out.print("**************************************"); 26 root.print(); 27 } 28 }
输出如下:
小结:这个模式理解起来并不困难,重点在于了解树形结构,然后掌握递归调用的写法,剩下的就相当简单了。
组合模式到此结束,♪(^∇^*)
参考资料:《Head First 设计模式》。