前面说过了,在Java类库中设计模式的踪影随处可见,因而要讲解所有出现的模式实
在是不可能,这儿主要把焦点聚集在AWT/Swing中,管中窥豹,却也可以了解设计模式的一
些深刻的含义所在。
2.1 Composite模式和Component-Container结构(3月13日)
Comosite用来将对象组合成树行结构以表示“部分-整体”的层次结构。并且能够将一
个组合对象简单化,将其作为单一对象处理。用Composite模式也可以很容易的构造出一个
对象树来,并能够方面的进行对象遍历。
在Java/AWT中Component-Container是最为明显的一个Composite模式的应用。Compone
nt类是所有AWT类的祖先,用来表示一个图形的组件。而Container类是说有容器的的抽象
父类,凡是继承了Container的类,都可以在其中容纳其它的Component类或者Container类
。我们下面的这个类图中很容易的就可以看到这种关系:
在AWT中的Panel,Applet, ScrollPane等等类都是Container类的子类,Windows类也
是,但却是一个异数,它,包括它的子类Frame和Dialog是顶级容器,并不能够被其他的容
器所包含。我们来看看这样的结构有什么样的作用。
首先,可以很容易的对界面中的所有元素进行组织。如果看仔细一点,你会发现上面
的那个类图实际上就是一个树。这样组织的结果使得对于组件的处理变得方便。而且通过
层层的递归,可以很方便的实现足够复扎的体系。
第二,你可以把Container当作一个独立的Component来操作,而不必理会它是否真的
是一个Container类。这样说好像有一点饶舌,举个例子你就明白了。在Component中又一
个validate()方法来用来显示组件,Container作为Comonent的子类,当然也会有validate
()方法,当然它的具体实现是不同于Component的。我们在使用validate()方法时,并不需
要理会它是被施用在Container类或者是被施用在Component类上。对于Container而言,当
validate()被调用后,它不仅要处理其自生的显示,而且要处理所有其子元素(子节点)
的显示,将validate()方法传递下去。但是对于客户而言,所作的只是把容器当作一个组
件调用了它的validate()方法,避免了琐碎的细节,简化了客户代码。
第三,Container可以代理一些它所包含的子Component的功能。例如,如果客户调用
一个组件的getFont()方法,但是在这个组件并没有显式的设定字体值,也就是说当前的Fo
nt属性不可用。那么getFont()可以被代理到其高层的容器上,如果这个容器Font属性不是
null,就会返回这个Font属性作为哪个子Component的getFont()方法的返回值。
我们在反过来看看Composite模式的一些细节,下面给出了Composite的类图:
Client考虑的只是Component中所定义的接口。当他进行接口调用的时候,如果是Leaf
,那么过程调用简单的进行,但如果是Composite,调用将会被传递给其所有的子Componen
t。这就是Composite模式的关键所在。当然,对于Composite而言,应该有一种数据结构来
保存其所有子Component的引用,并提供适当的方法来对这些子Component进行管理。
在Java/AWT中的菜单的结构也是Composite模式的一个例子,这儿就不再多讲了。