设计模式-组合模式(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 设计模式》。

 

posted @ 2016-07-23 15:14  呆代待殆  阅读(220)  评论(0编辑  收藏  举报