组合模式

来源:互联网 发布:网络电视机wifi 编辑:程序博客网 时间:2024/05/15 15:34

上一篇文章说了桥接模式可以处理多维度变化问题。这里讲另一种有用的设计模式:组合模式。

组合模式可以解决树形结构的问题,它一致性地处理树中的节点。如,在一个文件夹中有子文件夹和各种文件,子文件夹可以看做组合对象,而各种文件则是叶子对象。组合模式的关键在于它引入了一个抽象构件类,这个类既可以代表叶子,也可以代表容器,因此在客户端可以统一地对待叶子和容器。

以下是组合模式的结构图。


用一个例子来说明组合模式吧。假设现在要开发一个界面控件库,控件分为两类:单元控件,如按钮,文本框等;容器控件,窗体,中间面板等。以下是使用组合模式对这个库的简单实现。


需要注意的是,这张图和上一张图稍有不同,不同的原因在于叶子对象和容器对象客观存在的差异。叶子对象是不能有add,remove,getChild()这些方法的,这就导致了应该把这些方法放在哪里的问题,是放在抽象构件类,还是容器类。若是前者,则在抽象构件类的实现中这些方法都要抛出异常或其他类似错误处理,而在容器类中重写这些方法即可;若是后者,则容器类不能声明为抽象构件类型,因为抽象构件类没有定义那些方法。这两种处理方式也就是对应的透明组合模式和安全组合模式了。所谓透明,就是叶子对象和容器对象可以被统一看成构件类型,但这样的话,在叶子对象上调用上述方法时就要出错了,而安全组合模式虽然安全了,但容器类需要特殊对待了。

以下是代码的简单实现:

import java.util.LinkedList;public class EighthComposite {public static void main(String[] args) {// TODO Auto-generated method stubComponent button = new NewButton();Component textfield = new NewTextfield();Container window = new Window();Container panel = new Panel();window.add(button);panel.add(textfield);window.display();panel.display();}}abstract class Component{public abstract void display();}abstract class Cell extends Component{}class NewButton extends Cell{@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("显示Button");}}class NewTextfield extends Cell{@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("显示Textfield");}}abstract class Container extends Component{protected LinkedList<Component> children = new LinkedList<Component>();public void add(Component c){children.add(c);}public void remove(Component c){children.remove(c);}public Component getChild(int i){return children.get(i);}}class Window extends Container{public void display(){System.out.println("显示窗口,并在窗口中:");for(Component c:children){c.display();}}}class Panel extends Container{public void display(){System.out.println("显示面板,并在面板中:");for(Component c:children){c.display();}}}

输出:

显示窗口,并在窗口中:显示Button显示面板,并在面板中:显示Textfield

如此便较好地处理了这种树形结构的问题,好神奇。

0 0
原创粉丝点击