1、引入
Composite,译为复合物。乍一听复合物模式似乎有点云里雾里,不妨从以下角度来理解:
以操作系统中的文件夹为例,文件夹中存在着许多文件,包括但不限于:文件夹,文本文档,快捷方式等。这些文件种类繁多,一同组成了复合物(文件夹,容器)。而能够存进文件夹中的,虽然多种多样,但是它们都是文件(内容,存在共通性)。
而Composite模式就是这样的一种模式:能够在容器(复合物)中放入内容甚至更小的容器,更小的容器中又能放入内容和更更小的容器,形成一种递归结构。而能够实现这种结构,需要容器与内容具有一致性。
2、示例
还是以上文的文件夹为例。
2.1、文件夹与文件的统一抽象父类Entry
共同的父类实现了文件夹与文件的统一
public abstract class Entry {
public abstract String getName();
public abstract int getSize();
public Entry add(Entry entry)throws FileTreatMentException {
throw new FileTreatMentException();
}
public void printList() {
printList("");
}
protected abstract void printList(String prefix);
public String toString() {
return getName()+"("+getSize()+")";
}
}
2.2、File类
public class File extends Entry{
private String name;
private int size;
public File(String name, int size) {
this.name = name;
this.size = size;
}
@Override
public String getName() {
return name;
}
@Override
public int getSize() {
return size;
}
@Override
protected void printList(String prefix) {
System.out.println(prefix+"/"+this);
}
}
2.3、Directory类
实现了文件夹的添加等功能
public class Directory extends Entry{
private String name;
private ArrayList<Entry> dir=new ArrayList<>();
public Directory(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public int getSize() {
int size=0;
Iterator<Entry> iterator = dir.iterator();
while (iterator.hasNext()) {
size+=iterator.next().getSize();
}
return size;
}
public Entry add(Entry entry) {
dir.add(entry);
return this;
}
@Override
protected void printList(String prefix) {
System.out.println(prefix+"/"+this);
Iterator<Entry> iterator = dir.iterator();
while (iterator.hasNext()) {
iterator.next().printList(prefix+"/"+name);
}
}
}
2.4、测试
public class Main {
public static void main(String[] args) {
System.out.println("Making entries....");
Directory root = new Directory("root");
Directory bin = new Directory("bin");
Directory tmp = new Directory("tmp");
root.add(bin);
root.add(tmp);
bin.add(new File("vim", 1000));
bin.add(new File("ls", 500));
tmp.add(new File("mysql_log", 20000));
tmp.add(new File("system_security_log)",100000));
root.printList();
}
}
运行结果:
可以看出,实现了文件夹逐级递归访问
3、tips
- 这里Entry不使用接口原因是接口的修饰符固定为public,而被protected修饰的printList(String prefix)方法在接口中无法定义。
- Composite模式除了在文件夹中有着应用,在视窗系统、文章列表、宏命令合成等存在递归机构的系统中也广泛应用。