一、模式说明
能够使容器与内容物具有一致性,创造出递归结构的模式就是Composite组合模式。
举个例子:计算机中的文件系统中有文件和文件夹的概念,我们知道,文件夹可以包含文件,也可以包含子文件夹,子文件夹中又可以包含文件和文件夹。如果将文件和文件夹都看作“目录条目(Directory Entry)”,那么文件系统就形成了一个递归的容器,这就是一种组合模式。
更多例子,在Windows操作系统中,一个窗口中可以包含子窗口,从而形成容器的递归;一条宏命令又可以包含另一个宏命令;一个文章章节又可以包含多个子章节。。。这种具有树状结构的数据都适用于组合模式。
二、模式类图
三、代码示例
在示例程序中,我们创建一个Entry目录条目类,并让File文件类和Dictory文件夹类去继承它。
1、FileTreatementException类
package com.designpattern.cn.Entry; public class FileTreatementException extends RuntimeException { public FileTreatementException(){ } public FileTreatementException(String msg){ super(msg); } }
2、Entry条目类
package com.designpattern.cn.Entry; public abstract class Entry { public abstract String getName(); public abstract int getSize(); public Entry add(Entry entry) throws FileTreatementException{ throw new FileTreatementException(); } public void PrintList(){ printList(""); } protected abstract void printList(String prefix); public String toString(){ return getName() + " (" + getSize() + ")"; } }
3、File文件类
package com.designpattern.cn.Entry; public class File extends Entry { private String name; private int size; public File(String name, int size){ this.name = name; this.size = size; } public String getName(){ return name; } public int getSize(){ return size; } protected void printList(String prefix){ System.out.println(prefix + "/" + this); } }
4、Directory目录类
package com.designpattern.cn.Entry; import java.util.ArrayList; import java.util.Iterator; public class Directory extends Entry { private String name; private ArrayList directory = new ArrayList(); public Directory(String name){ this.name = name; } public String getName(){ return name; } public int getSize(){ int size = 0; Iterator it = directory.iterator(); while (it.hasNext()){ Entry entry = (Entry) it.next(); size += entry.getSize(); } return size; } public Entry add(Entry entry){ directory.add(entry); return this; } protected void printList(String prefix){ System.out.println(prefix + "/" + this); Iterator it = directory.iterator(); while (it.hasNext()){ Entry entry = (Entry) it.next(); entry.printList(prefix + "/" + name); } } }
5、Main方法类和运行结果
package com.designpattern.cn.Entry; public class Main { public static void main(String[] args) { try { System.out.println("Making root entries..."); Directory rootdir = new Directory("root"); Directory bindir = new Directory("bin"); Directory tmpdir = new Directory("tmp"); Directory usrdir = new Directory("usr"); rootdir.add(bindir); rootdir.add(tmpdir); rootdir.add(usrdir); bindir.add(new File("vi", 10000)); bindir.add(new File("latex", 20000)); rootdir.printList(""); }catch (FileTreatementException e){ e.printStackTrace(); } } }
四、模式中的角色
- Leaf树叶角色:该角色中不能再放入其他对象,如示例中的File类;
- Composite复合物类:在其中可以放入Leaf和Composite复合物,如示例程序中的Directory类;
- Component类:使Leaf和Composite角色具有一致性的角色,如示例中的Entry类;
- Client客户角色:使用复合模式的对象。
五、相关的设计模式
- Command模式:Command模式编写宏命令时会使用Composite模式;
- Vistor访问者模式:可以使用访问者模式访问Composite中的递归结构;
- Decorator装饰者模式:Composite模式通过Component角色使Composite和Leaf具有一致性,Decorator模式使装饰框和内容具有一致性;