组合模式(Composite Pattern):
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite 使得客户对单个对象和复合对象的使用具有一致性。(Compose object into tree structures torepresent part-whole hierarchy. Composite lets clients treat individual objectsand compositions of objects uniformly.)
组合模式的优缺点:
优点:
- 可以清楚地定义分层次的复杂类型,表示对象的全部层次或者部分层次 ,它让客户端忽略了层次的差异,方便对整个层次经行控制。
- 客户端可以一致的使用一个组合模式或对单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端的代码。
- 在组合模式种增加新的容器构件和叶子构件都很方便,无需对现有类库进行任何修改,符合开闭原则。
- 为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合可以形成复杂的树形机构,但对树形结构的控制却很简单。
缺点:
在增加新的构件时就比较难咯。而且难以限定,有时候希望在一个容器种能有某些特定的对象,例如在某个文件夹只能有image或者gif等。这个就比较难以实现。
开发中的应用场景:
组合模式核心 :
案例:使用组合模式,模拟杀毒软件,该软件能够对某个文件夹杀毒,也可以指定对某些文件杀毒。该过程大致可分为4步,代码如下:
步骤1:定义AbstractFile : 抽象文件类,充当抽象构建。
/**
* AbstractFile: 抽象文件类,充当抽象构建。
*/
public abstract class AbstractFiles {
public abstract void add(AbstractFiles af);
public abstract void remove(AbstractFiles af);
public abstract AbstractFiles get(int i);
public abstract void killVirus();
}
步骤2:定义叶子节点:文件类型,在此只写了图片文件。
/**
* 图片文件,继承自AbstractFiles
*/
public class ImageFile extends AbstractFiles {
private String name;
public ImageFile(String name) {
this.name = name;
}
@Override
public void add(AbstractFiles af) {
System.out.println("不支持该方法");
}
@Override
public void remove(AbstractFiles af) {
System.out.println("不支持该方法");
}
@Override
public AbstractFiles get(int i) {
System.out.println("不支持该方法");
return null;
}
@Override
public void killVirus() {
System.out.println("开始进行--"+name+"--文件杀毒");
}
}
步骤3:文件夹类型
import java.util.ArrayList;
/**
* 文件夹类型 ,继承自AbstractFiles
*/
public class Folder extends AbstractFiles {
//文件夹类,所有的都可以用
private ArrayList<AbstractFiles> list = new ArrayList<AbstractFiles>();
private String name;
public Folder(String name) {
this.name=name;
}
@Override
public void add(AbstractFiles af) {
list.add(af);
System.out.println("添加文件成功!");
}
@Override
public void remove(AbstractFiles af) {
if(list.remove(af)) {
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
}
@Override
public AbstractFiles get(int i) {
return list.get(i);
}
@Override
public void killVirus() {
System.out.println("对文件夹 "+name+" 进行杀毒");
//递归调用
for(Object o:list) {
((AbstractFiles) o).killVirus();
}
}
}
步骤4:测试
/**
* 测试
*/
public class Client {
public static void main(String[] args) {
//创建一个文件类型
AbstractFiles f1 = new Folder("主文件夹");
//创建文件
AbstractFiles file1= new ImageFile("美妙月亮。png");
AbstractFiles file2= new ImageFile("大海.jpg");
AbstractFiles file3= new ImageFile("沙漠杨树.gif");
f1.add(file1);
f1.add(file2);
f1.add(file3);
//file1.killVirus();
f1.killVirus();
}
}
如果想了解更多设计模式,可点击:设计模式概述 以及 23种设计模式的介绍