Composite模式即组合模式。它能够使容器和内容具有一致性,创造出递归结构。
举个例子:在文件系统中,文件夹既是内容,也是容器,具有一致性,这样一来,文件系统形成递归结构。组合模式就是用来创建这种结构的。
代码
下面这段代码以文件系统为例实现了组合模式。
UML
Entry类
表示目录条目,将文件和文件夹的共有属性抽取出来。
public abstract class Entry {
public abstract String getName();
public abstract int getSize();
public Entry add(Entry entry) throws RuntimeException {
throw new RuntimeException();
}
public void printList() {
printList("");
}
protected abstract void printList(String prefix);
public String toString() {
return getName() + " (size : " + getSize() + ")";
}
}
File类
表示文件
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);
}
}
Directory类
表示文件夹
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);
}
}
}
Main类
public class Main {
public static void main(String[] args) {
try {
System.out.println("创建根目录");
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();
System.out.println("");
System.out.println("创建用户目录");
Directory xiaoming = new Directory("小明");
Directory xiaohong = new Directory("小红");
Directory xiaohua = new Directory("小花");
usrdir.add(xiaoming);
usrdir.add(xiaohong);
usrdir.add(xiaohua);
xiaoming.add(new File("diary.html", 100));
xiaoming.add(new File("Composite.java", 200));
xiaohua.add(new File("memo.tex", 300));
xiaohong.add(new File("game.doc", 400));
xiaohong.add(new File("junk.mail", 500));
rootdir.printList();
} catch (FileTreatmentException e) {
e.printStackTrace();
}
}
}
结果
/*
创建根目录
/root (size : 30000)
/root/bin (size : 30000)
/root/bin/vi (size : 10000)
/root/bin/latex (size : 20000)
/root/tmp (size : 0)
/root/usr (size : 0)
创建用户目录
/root (size : 31500)
/root/bin (size : 30000)
/root/bin/vi (size : 10000)
/root/bin/latex (size : 20000)
/root/tmp (size : 0)
/root/usr (size : 1500)
/root/usr/小明 (size : 300)
/root/usr/小明/diary.html (size : 100)
/root/usr/小明/Composite.java (size : 200)
/root/usr/小红 (size : 900)
/root/usr/小红/game.doc (size : 400)
/root/usr/小红/junk.mail (size : 500)
/root/usr/小花 (size : 300)
/root/usr/小花/memo.tex (size : 300)
*/
角色
Component:是Leaf和Composite角色的父类,包含这两个角色具有的一致性的信息。在本例中由Entry扮演此角色。
Leaf:表示内容的角色,里面不能再放入其他对象。本例中由File来扮演此角色。
Composite:表示容器的角色,里面可以放入Leaf或Composite角色。本例中由Directory扮演此角色。
Client:使用Composite模式的角色,本例中由Main来扮演。
UML
想法
这个模式非常能体现递归的思想。Composite继承并组合了Component,好好体会一下。