定义
将对象组合成树形结构表示<font color="#ooccss">整体-部分</font>的层次结构,使得用户对每个单个对象和组合对象的使用具有一致性
使用场景
表示对象的部分-整体层次结构时
从一个整体中能够独立出部分模块或功能的场景
模式结构
- Component 抽象根节点,为组合中的对象声明接口
- Composite 定义有子节点的那些枝干节点的行为,存储子节点,在 Component 接口中实现与子节点有关的操作
- Leaf 在组合中表示叶子节点对象,叶子节点没有子节点,在组合中定义节点对象的行为
- Client 通过 Component 接口操纵组合节点的对象
简单实现
操作系统的文件系统就是一种典型的组合模式例子,Android中View与ViewGroup构成的UI体系也是很典型的实现。
下面以一个简单的文件系统来做说明
public abstract class Dir {
/**
* 声明一个 list 成员变量存储文件夹下的所有元素
*/
protected List<Dir> dirs = new ArrayList<>();
private String name;
public Dir(String name) {
this.name = name;
}
/**
* 添加一个文件或文件夹
*
* @param dir 文件或文件夹
*/
public abstract void addDir(Dir dir);
/**
* 删除一个文件或文件夹
*
* @param dir 文件或文件夹
*/
public abstract void rmDir(Dir dir);
/**
* 清空文件夹下所有元素
*/
public abstract void clear();
/**
* 输出文件夹目录结构
*/
public abstract void print();
/**
* 获取文件夹下所有文件或子文件夹
*
* @return 文件夹下所有文件或子文件夹
*/
public abstract List<Dir> getFiles();
/**
* 获取文件或文件夹名
*
* @return 文件或文件夹名
*/
public String getName() {
return name;
}
}
public class File extends Dir {
public File(String name) {
super(name);
}
@Override
public void addDir(Dir dir) {
throw new UnsupportedOperationException("文件对象不支持该操作");
}
@Override
public void rmDir(Dir dir) {
throw new UnsupportedOperationException("文件对象不支持该操作");
}
@Override
public void clear() {
throw new UnsupportedOperationException("文件对象不支持该操作");
}
@Override
public void print() {
System.out.print(getName());
}
@Override
public List<Dir> getFiles() {
throw new UnsupportedOperationException("文件对象不支持该操作");
}
}
文件为叶子节点,不能作为文件夹来使用,它相对于文件夹来说既不支持添加也不支持删除,这里直接抛出一个不支持异常来简单处理。
public class Folder extends Dir {
public Folder(String name) {
super(name);
}
@Override
public void addDir(Dir dir) {
dirs.add(dir);
}
@Override
public void rmDir(Dir dir) {
dirs.remove(dir);
}
@Override
public void clear() {
dirs.clear();
}
@Override
public void print() {
System.out.print(getName() + " (");
Iterator<Dir> iterator = dirs.iterator();
while (iterator.hasNext()) {
Dir dir = iterator.next();
dir.print();
if (iterator.hasNext()) {
System.out.print(", ");
}
}
System.out.print(") ");
}
@Override
public List<Dir> getFiles() {
return dirs;
}
}
public class Client {
public static void main(String[] args) {
Dir disk = new Folder("木叶");
File file = new File("火影");
disk.addDir(file);
Dir high = new Folder("上忍");
disk.addDir(high);
Dir low = new Folder("下忍");
disk.addDir(low);
Dir elite = new Folder("精英上忍");
high.addDir(elite);
elite.addDir(new File("卡卡西 "));
Dir general = new Folder("普通上忍");
high.addDir(general);
general.addDir(new File("宁次"));
low.addDir(new File("鸣人"));
low.addDir(new File("佐助"));
disk.print();
System.out.println("\n---------------------\n");
disk.rmDir(file);
disk.print();
}
}
输出结果:
木叶 (火影, 上忍 (精英上忍 (卡卡西 ) , 普通上忍 (宁次) ) , 下忍 (鸣人, 佐助) )
---------------------
木叶 (上忍 (精英上忍 (卡卡西 ) , 普通上忍 (宁次) ) , 下忍 (鸣人, 佐助) )
Process finished with exit code 0