毫无疑问的,AWT中的Component-Container体系就是一个很好的Composite模式的例子。Container继承于Component,而Container中有可以包含有多个Component,因为Container实际上也是Component,因而Container也可以包含Container。这样通过Component-Container结构的对象组合,形成一个树状的层次结构。这也就是Composite模式所要做的。
Composite模式是为了简化编程而提出的,一般的在编程的时候,如果严格的区分Component和Container的话,有时候会带来许多不便,而且这些往往是没有必要的。比如,我要在一个Container中放置一个Component,我并不需要知道这个Component到底是一个Container,或者就是一个一般的Component,在父级容器中所要做的,只是记录一个Component的引用,在需要的时候调用Component的绘制方法来显示这个Component。当这个Component确实是一个Container的时候,它可以通过Container重载后的绘制方法,完成对这个容器的显示,并把绘制消息传递给到它的子对象去。也就是说,对一个父级容器而言,它并不不关心,其子对象到底是一个Component,还是一个Container。它需要将Component和Container统一对待。
图十一:Composite模式的类图
Composite模式比较简单,实现起来也不复杂,但是有一定的局限性。比如,在处理树的时候,我们往往需要处理三类对象:子树,页节点和非页节点。而在Composite模式中对于子树和非叶节点的区分并不明显,而是把他们合成为一个Composite对象了。而且在GOF给出的Composite的模式中,对于添加,删除子节点等属于Composite对象的的方法,是放在了Component对象中的,这虽然在实现的时候可以区分开来,但容易造成一些概念上的误解。
由上所叙,我们可以提出一个改进了的Composite模式,引入子树对象,从而将子树和非叶节点分开,如下图所示:
图十二:Composite模式的一种变体
虽然将Composite从Component类层次中分离出来,但并没有损害Composite模式的内涵。这样做不一定就会比上面的那个要好,各有不同的应用,不过有时候用这样的方法来处理子树要容易些,概念上也更为清晰。
下面的代码,给出了一个Composite模式简单的Java实现:
2
3 public abstract void operation();
4
5 public void add(Component component){};
6
7 public void remove(Component component){};
8
9 }
10
11 import java.util.*;
12
13 public class Composite extends Component{
14
15 String name;
16
17 ArrayList children = new ArrayList();
18
19 public Composite(String name){
20
21 this.name = name;
22
23 }
24
25 public void add(Component component){
26
27 children.add(component);
28
29 }
30
31 public void remove(Component component){
32
33 children.remove(component);
34
35 }
36
37 public void operation(){
38
39 System.out.println(name);
40
41 Iterator iterator = children.iterator();
42
43 while(iterator.hasNext()){
44
45 Component child = (Component)iterator.next();
46
47 child.operation();
48
49 }
50
51 }
52
53 }
54
55 public class Leaf extends Component{
56
57 String name;
58
59 public Leaf(String name){
60
61 this.name = name;
62
63 }
64
65 public void operation(){
66
67 System.out.println(name);
68
69 }
70
71 }
72