什么是组合模式
将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象以及组合对象的适用具有一致性。
组合模式又称为部分整体模式,他主要是根据一个树状结构来确定要归纳为同一类的对象,从而以同样的方法去访问对象和对象组合,忽略掉他们之间的差别。比如根文件下有文件和子文件夹,子文件夹下还会有文件和子文件夹……这个如果我们要写一个类来层次描述他们,岂不是要写很多很多。使用组合模式就是把文件和文件夹不加以区别,统称为文件对象。
组合模式的适用场景
表示“部分-整体”的层次结构时
一个整体中可以独立出部分模块和功能的场景
组合模式用例
文件夹下可以存放文件夹和文件,这个子文件夹下还可以存放文件和文件夹….我们现在要做的就是获得这个文件系统的结构图。
UML类图
AbstractFile抽象类
public abstract class AbstractFile {
protected List<AbstractFile> afs = new ArrayList<>();
protected String mName;
public AbstractFile(String name){
mName = name;
}
public abstract void mAdd(AbstractFile af);
public abstract void mRemove(AbstractFile af);
public abstract void printName();
}
Files类
public class Files extends AbstractFile {
public Files(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void mAdd(AbstractFile af) {
// TODO Auto-generated method stub
}
@Override
public void mRemove(AbstractFile af) {
// TODO Auto-generated method stub
}
@Override
public void printName() {
System.out.println("....."+mName);
}
}
Folders类
public class Folders extends AbstractFile {
public Folders(String name) {
super(name);
}
@Override
public void mAdd(AbstractFile af) {
afs.add(af);
}
@Override
public void mRemove(AbstractFile af) {
afs.remove(af);
}
@Override
public void printName() {
System.out.println(mName);
for(AbstractFile f : afs){
f.printName();
}
}
}
主类调用
public class Test {
public static void main(String[] args) {
AbstractFile apk = new Files("1.apk");
AbstractFile text = new Files("1.txt");
AbstractFile png = new Files("1.png");
AbstractFile folder1 = new Folders("folder1");
folder1.mAdd(text);
folder1.mAdd(png);
folder1.mAdd(apk);
AbstractFile jpg = new Files("1.jsp");
AbstractFile exe = new Files("1.exe");
AbstractFile folder2 = new Folders("folder2");
folder2.mAdd(jpg);
folder2.mAdd(exe);
AbstractFile folder = new Folders("Folder");
folder.mAdd(folder1);
folder.mAdd(folder2);
folder.printName();
}
}
运行结果:
Folder
folder1
.....1.txt
.....1.png
.....1.apk
folder2
.....1.jsp
.....1.exe
总结:
经过分析以上代码,我们明白了组合就是同一对象操作,通过递归来遍历对象树,从而达到我们的目的。
优点是简化了操作,清楚了分层,方便对整个层次结构的控制。添加树子叶方便,符合开闭原则。
缺点是违背了单一职责原则,而且通过继承实现,代码的灵活性降低。而且新增构件又会复杂一点,比如要在文件操作中增加mClear()操作,又要去修改抽象类以及实现。