“部分-整体“——组合模式
一、组合模式概述
1.定义:
组合模式(Composite),将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
2.例子:
3.分析:
在树形目录结构中,包含文件和文件夹两类不同的元素。
在文件夹中可以包含文件,还可以继续包含子文件夹,在文件中不能再包含子文件或者子文件夹。
文件夹 —>容器(Container)
文件 —>叶子(Leaf)
4.理解:
一致地对待容器对象和叶子对象。
当容器对象的某一个方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员对象并调用执行,牵一而动百,其中使用了递归调用的机制来对整个结构进行处理
由于容器对象和叶子对象在功能上的区别,在使用这些对象的代码中必须有区别地对待容器对象和叶子对象,而实际上大多数情况下客户端希望一致地处理它们,因为对于这些对象的区别对待将会使程序非常复杂
5.结构:
组合模式包含以下3个角色:Component(抽象构件)、Leaf(叶子构件)、Composite(容器构件)
二、组合模式适用环境
1.在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们
2.在一个使用面向对象语言开发的系统中需要处理一个树形结构
3.在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型
三、组合模式案例
1.案例:
软件公司欲开发一个杀毒软件,该软件既可以对某个文件夹(Folder)杀毒,也可以对某个指定的文件(File)进行杀毒。该杀毒软件还可以根据各类文件的特点,为不同类型的文件提供不同的杀毒方式,例如图像文件(ImageFile)和文本文件(TextFile)的杀毒方式就有所差异。现使用组合模式来设计该杀毒软件的整体框架。
2.类图:
(1) AbstractFile:抽象文件类,充当抽象构件类
(2) ImageFile:图像文件类,充当叶子构件类
(3) TextFile:文本文件类,充当叶子构件类
(4) Folder:文件夹类,充当容器构件类
(5) Client:客户端测试类
3.代码:
package composite;
/**
* 抽象文件类,充当抽象构件类
*/
public abstract class AbstractFile {
public abstract void add(AbstractFile file); //添加元素
public abstract void remove(AbstractFile file); //删除元素
public abstract void killVirus(); //模拟杀毒
}
package composite;
import java.util.ArrayList;
/**
* 文件夹类,充当容器构件类
*/
public class Folder extends AbstractFile {
//定义一个fileList的集合,用来存储AbstractFile类型的成员
private ArrayList<AbstractFile> fileList = new ArrayList<>();
private String name; //定义文件夹名
//无参构造
public Folder() {
}
//有参构造
public Folder(String name) {
this.name = name;
}
@Override
public void add(AbstractFile file) {
fileList.add(file);
}
@Override
public void remove(AbstractFile file) {
fileList.remove(file);
}
@Override
public void killVirus() {
System.out.println("系统正在对‘" + name + "’进行杀毒");
//利用foreach循环对fileList集合里的所有元素进行杀毒
for (AbstractFile abstractFile : fileList) {
abstractFile.killVirus();
}
}
}
package composite;
/**
* 图像文件类,充当叶子构件类
*/
public class ImageFile extends AbstractFile {
private String name; //定义文件名
//无参构造
public ImageFile() {
}
//有参构造
public ImageFile(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 void killVirus() {
System.out.println("系统正在对‘" + name + "’进行图像杀毒");
}
}
package composite;
/**
* 文本文件类,充当叶子构件类
*/
public class TextFile extends AbstractFile {
private String name; //定义文件名
//无参构造
public TextFile() {
}
//有参构造
public TextFile(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 void killVirus() {
System.out.println("系统正在对‘" + name + "’进行文本杀毒");
}
}
package composite;
/**
* 客服端测试类
*/
public class Client {
public static void main(String[] args) {
/*
1.创建对象
*/
//创建文件夹对象
AbstractFile folder = new Folder("Bei-Zhen的资料");
//创建子文件夹对象
AbstractFile subfolder1 = new Folder("图像文件夹");
AbstractFile subfolder2 = new Folder("文本文件夹");
//创建文件对象(图像文件或文本文件)
AbstractFile file1 = new ImageFile("百度登录流程图.jpg");
AbstractFile file2 = new ImageFile("猜拳流程图.png");
AbstractFile file3 = new TextFile("设计模式.txt");
AbstractFile file4 = new TextFile("面向对象基础.doc");
/*
2.向集合中添加元素
*/
//把文件添加到相对应的子文件夹中
subfolder1.add(file1);
subfolder1.add(file2);
subfolder2.add(file3);
subfolder2.add(file4);
//把子文件夹添加到文件夹中
folder.add(subfolder1);
folder.add(subfolder2);
/*
3.对文件夹杀毒
*/
System.out.println("---------------杀毒软件--------------------");
System.out.println("------文件夹杀毒开始,正在闪电杀毒-----------");
folder.killVirus();
System.out.println("------文件夹杀毒完成,感谢你的使用-----------");
System.out.println();
/*
4.对指定文件杀毒
*/
System.out.println("------指定文件杀毒开始,正在闪电杀毒---------");
file1.killVirus();
System.out.println("------指定文件杀毒完成,感谢你的使用---------");
}
}
4.代码运行截图:
四、组合模式优缺点
1.优点:
(1)可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,让客户端忽略了层次的差异,方便对整个层次结构进行控制
(2)客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码
(3)增加新的容器构件和叶子构件都很方便,符合开闭原则
(4)为树形结构的面向对象实现提供了一种灵活的解决方案
2.缺点:
在增加新构件时很难对容器中的构件类型进行限制
本文地址:https://blog.csdn.net/qq_33591873/article/details/107595527