本文由原创,转载请注明出处:
前置技能:认识数据结构中的树形结构。
组合模式简介
组合模式是将对象组合成树形结构以表示“部分-整体”的层次结构,每一个节点可以是叶子节点也可以使包含一堆子节点的中间节点,而且所有的节点都有同样的接口,用户在使用的时候无需区分节点类型,也就是可以将整个结构的任意部分当成“整体”来处理,这就是组合模式带来的方便。
组合模式的定义和基本结构
定义:将对象组合成树形结构以表示“部分-整体”的层次结构,并且为不同类型的节点提供完全相同的接口,让用户可以将整个结构的任意部分当成“整体”来处理。
一张来自《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 ArrayListlist; 4 public MyComposite(String s) { 5 super(s); 6 list=new ArrayList (); 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 @Override16 public void add(Component s) {17 list.add(s);18 }19 @Override20 public void remove(Component s) {21 if(!list.remove(s)){22 for(Component c:list)23 c.remove(s);24 }25 }26 @Override27 public Component getChild(int i) {28 if(i
然后实现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 设计模式》。