目录
介绍
组合模式也称为整体模式,是结构型设计模式之一,它将一组相似的对象看作一个整体对象处理,并根据一个树状结构来组合对象,然后提供一个统一的方法去访问相应的对象,以此忽略掉对象与对象集合之间的差异,生活中比较常见的就是组织结构图,比如总公司是结构的顶点,它下面包含了深圳、上海、西安、成都分公司,还是总行政部、总财务部等等部门,而深圳、上海、西安、成都分公司又包含了自己的下属部门,这样就构成一层一层的树状结构,而总行政部、总财务部和叶子节点,和深圳、上海、西安、成都分公司是平齐的,在同一层级上的。
定义
将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性,而忽略掉两者的差异。
使用场景
1、表示对象的部分-整体层次结构时;2、从一个整体中能够独立出部分模块或功能的场景。
代码实现
我们以文件夹结构为例来用伪代码实现一下,定义Dir抽象类,代码如下:
public abstract class Dir {
protected List<Dir> dirs = new ArrayList<>();
private String mName;
public Dir(String name) {
mName = name;
}
public abstract void addDir(Dir dir);
public abstract void rmDir(Dir dir);
public abstract void clear();
public abstract void print();
public abstract List<Dir> getFiles();
public String getName() {
return mName;
}
}
文件夹的结构树下存在目录和文件两种对象,分别是Folder和File,源码如下:
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.println(getName() + "(");
Iterator<Dir> iterator = dirs.iterator();
while (iterator.hasNext()) {
Dir dir = iterator.next();
if (iterator.hasNext()) {
System.out.println(", ");
}
}
System.out.println(")");
}
@Override
public List<Dir> getFiles() {
return dirs;
}
}
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.println(getName());
}
@Override
public List<Dir> getFiles() {
throw new UnsupportedOperationException("文件没有子文件");
}
}
这样我们就把文件夹的树状结构描述出来了,在Android源码中也有很多组合模式的例子,经典的View系统就是一个很好的例子,ViewGroup就对应这里的目录Folder,它可以添加子View,这样一层一层的View或者ViewGroup组合起来就构成了我们的主界面,其中的叶子节点可以是各种各样的实例,比如TextView、Button、ImageView、Checkbox、RecycleView等等,所有的叶子节点都是View的子类,通过measure、layout、draw这三个方法来测量、布局、绘制,然后把自己显示在主界面上。