组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象
组合模式的结构
1.**Component(抽象构建):**它可以是接口或抽象类,为叶子构件和容器构件对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现
2.**Leaf(叶子节点):**他在组合结构中表示叶子节点对象,叶子节点没有子节点,它实现了在抽象构建中定义的行为
3.**Composite(容器构件):**他在组合结构中表示容器节点对象,容器节点包含子节点,每一个节点也可以是容器节点或者是子节点
下面是一个案例
某软件公司要开发一个杀毒软件,该软件既可以对某个文件夹杀毒,也可以对某个指定的文件杀毒。这个文件可以是不同种类的文件,例如图像文件和文本文件的杀毒方式也不一样,现在使用组合模式来构建整体的框架
Component角色,后面所有的组件都会继承这个类
package com.designpatten.composite.demo01;
public abstract class AbstractFile {
public abstract void add(AbstractFile file);
public abstract void remove(AbstractFile file);
/**
* 如果它的实现类是文件夹的话,那他就有子类了
* @param index
* @return
*/
public abstract AbstractFile getChild(int index);
/**
* 杀毒的方法
*/
public abstract void killVirus();
}
leaf叶子节点
package com.designpatten.composite.demo01;
import com.designpatten.bridge.demo1.Image;
public class ImageFile extends AbstractFile {
/**
* 文件的名称
*/
private String name;
ImageFile(){
}
ImageFile(String name){
this.name = name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void add(AbstractFile file) {
System.out.println("该文件类型,不支持该方法");
}
@Override
public void remove(AbstractFile file) {
System.out.println("该文件类型,不支持该方法");
}
@Override
public AbstractFile getChild(int index) {
return null;
}
@Override
public void killVirus() {
System.out.println("对于-----图片文件:"+name+"------进行杀毒");
}
}
package com.designpatten.composite.demo01;
import com.designpatten.factory.absfactory.TextField;
public class TextFile extends AbstractFile {
/**
* 文件类型的文件,只有一个名字
*/
private String name;
TextFile(){
}
TextFile(String name){
this.name = name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void add(AbstractFile file) {
System.out.println("对不起,该文件类型不支持这个方法");
}
@Override
public void remove(AbstractFile file) {
System.out.println("对不起,该文件类型不支持这个方法");
}
@Override
public AbstractFile getChild(int index) {
return null;
}
@Override
public void killVirus() {
System.out.println("对-------文本文件:" + name + "-------进行杀毒");
}
}
Composite容器节点,这个节点下面可以是叶子节点,也可以继续套容器节点
package com.designpatten.composite.demo01;
import java.util.ArrayList;
import java.util.List;
/**
* 文件夹的类
*/
public class Folder extends AbstractFile {
private String name;
private List<AbstractFile> list;
Folder() {
name = "新建文件夹";
list = new ArrayList<>();
}
Folder(String name){
this();
this.name = name;
}
@Override
public void add(AbstractFile file) {
list.add(file);
}
@Override
public void remove(AbstractFile file) {
list.remove(file);
}
@Override
public AbstractFile getChild(int index) {
if (index < 0 || index >= list.size()) {
System.out.println("输入的index错误");
return null;
}
return list.get(index);
}
@Override
public void killVirus() {
System.out.println("对于******文件夹:" + name + "*******进行杀毒");
for (AbstractFile file : list) {
file.killVirus();
}
}
}
客户端代码
package com.designpatten.composite.demo01;
public class Client {
public static void main(String[] args) {
Folder folder1 = new Folder();
Folder folder2 = new Folder("新建文件夹2");
ImageFile img1 = new ImageFile("图片文件1");
ImageFile img2 = new ImageFile("图片文件2");
TextFile text1 = new TextFile("文本文件1");
TextFile text2 = new TextFile("文本文件2");
folder1.add(folder2);
folder1.add(img1);
folder1.add(text1);
folder2.add(img2);
folder2.add(text2);
folder1.killVirus();
}
}
运行结果
通过这种方式可以构件一种树形结构,对于文件的层次比较清晰,对于容器对象和叶子对象进行了递归组合,灵活性比较高。
组合模式的优点
1.可以清楚的定义分层次的复杂对象
2.客户端可以一致地使用一个组合结构或其中的单个对象,不必关心处理的单个对象还是组合对象
3.在组合模式中不管是添加组合对象还是单个对象都很方便
4.为树形结构的面向对象实现提供了一种灵活的解决方案