“Github:https://github.com/nateshao/design-demo/tree/main/JavaDesignPatterns/10-bridge
Windows操作系统目录结构
分析
分析
如何一致地对待容器对象和叶子对象?
“组合模式通过一种巧妙的设计方案使得用户可以一致性地处理整个树形结构或者树形结构的一部分,它描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无须对它们进行区分,可以一致地对待容器对象和叶子对象。
定义
“组合模式:组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。
对象结构型模式
Part-Whole
)模式组合模式的结构
组合模式包含以下3个角色:
Component
(抽象构件)Leaf
(叶子构件)Composite
(容器构件)抽象构件角色典型代码:
AbstractFile.java
package com.nateshao.composite;
/**
* @date Created by 邵桐杰 on 2021/10/20 20:34
* @微信公众号 程序员千羽
* @个人网站 www.nateshao.cn
* @博客 https://nateshao.gitee.io
* @GitHub https://github.com/nateshao
* @Gitee https://gitee.com/nateshao
* Description:
*/
public abstract class AbstractFile {
public abstract void add(AbstractFile file);
public abstract void remove(AbstractFile file);
public abstract AbstractFile getChild(int i);
public abstract void killVirus();
}
VideoFile.java
package com.nateshao.composite;
/**
* @date Created by 邵桐杰 on 2021/10/20 20:34
* @微信公众号 程序员千羽
* @个人网站 www.nateshao.cn
* @博客 https://nateshao.gitee.io
* @GitHub https://github.com/nateshao
* @Gitee https://gitee.com/nateshao
* Description:
*/
public class VideoFile extends AbstractFile {
private String name;
public VideoFile(String name) {
this.name = name;
}
public void add(AbstractFile file) {
System.out.println("对不起,不支持该方法!");
}
public void remove(AbstractFile file) {
System.out.println("对不起,不支持该方法!");
}
public AbstractFile getChild(int i) {
System.out.println("对不起,不支持该方法!");
return null;
}
public void killVirus() {
//模拟杀毒
System.out.println("----对视频文件'" + name + "'进行杀毒");
}
}
TextFile.java
package com.nateshao.composite;
/**
* @date Created by 邵桐杰 on 2021/10/20 20:35
* @微信公众号 程序员千羽
* @个人网站 www.nateshao.cn
* @博客 https://nateshao.gitee.io
* @GitHub https://github.com/nateshao
* @Gitee https://gitee.com/nateshao
* Description:
*/
public class TextFile extends AbstractFile{
private String name;
public TextFile(String name) {
this.name = name;
}
public void add(AbstractFile file) {
System.out.println("对不起,不支持该方法!");
}
public void remove(AbstractFile file) {
System.out.println("对不起,不支持该方法!");
}
public AbstractFile getChild(int i) {
System.out.println("对不起,不支持该方法!");
return null;
}
public void killVirus() {
//模拟杀毒
System.out.println("----对文本文件'" + name + "'进行杀毒");
}
}
ImageFile.java
package com.nateshao.composite;
/**
* @date Created by 邵桐杰 on 2021/10/20 20:37
* @微信公众号 程序员千羽
* @个人网站 www.nateshao.cn
* @博客 https://nateshao.gitee.io
* @GitHub https://github.com/nateshao
* @Gitee https://gitee.com/nateshao
* Description:
*/
public class ImageFile extends AbstractFile {
private String name;
public ImageFile(String name) {
this.name = name;
}
public void add(AbstractFile file) {
System.out.println("对不起,不支持该方法!");
}
public void remove(AbstractFile file) {
System.out.println("对不起,不支持该方法!");
}
public AbstractFile getChild(int i) {
System.out.println("对不起,不支持该方法!");
return null;
}
public void killVirus() {
//模拟杀毒
System.out.println("----对图像文件'" + name + "'进行杀毒");
}
}
Folder.java
package com.nateshao.composite;
import java.util.ArrayList;
/**
* @date Created by 邵桐杰 on 2021/10/20 20:38
* @微信公众号 程序员千羽
* @个人网站 www.nateshao.cn
* @博客 https://nateshao.gitee.io
* @GitHub https://github.com/nateshao
* @Gitee https://gitee.com/nateshao
* Description:
*/
public class Folder extends AbstractFile {
//定义集合fileList,用于存储AbstractFile类型的成员
private ArrayList<AbstractFile> fileList = new ArrayList<AbstractFile>();
private String name;
public Folder(String name) {
this.name = name;
}
public void add(AbstractFile file) {
fileList.add(file);
}
public void remove(AbstractFile file) {
fileList.remove(file);
}
public AbstractFile getChild(int i) {
return (AbstractFile) fileList.get(i);
}
public void killVirus() {
System.out.println("****对文件夹'" + name + "'进行杀毒"); //模拟杀毒
//递归调用成员构件的killVirus()方法
for (Object obj : fileList) {
((AbstractFile) obj).killVirus();
}
}
}
Client.java
package com.nateshao.composite;
/**
* @date Created by 邵桐杰 on 2021/10/20 20:39
* @微信公众号 程序员千羽
* @个人网站 www.nateshao.cn
* @博客 https://nateshao.gitee.io
* @GitHub https://github.com/nateshao
* @Gitee https://gitee.com/nateshao
* Description:
*/
public class Client {
public static void main(String args[]) {
//针对抽象构件编程
AbstractFile file1, file2, file3, file4, file5, folder1, folder2, folder3, folder4;
folder1 = new Folder("Sunny的资料");
folder2 = new Folder("图像文件");
folder3 = new Folder("文本文件");
folder4 = new Folder("视频文件");
file1 = new ImageFile("小龙女.jpg");
file2 = new ImageFile("张无忌.gif");
file3 = new TextFile("九阴真经.txt");
file4 = new TextFile("葵花宝典.doc");
file5 = new VideoFile("笑傲江湖.rmvb");
folder2.add(file1);
folder2.add(file2);
folder3.add(file3);
folder3.add(file4);
folder4.add(file5);
folder1.add(folder2);
folder1.add(folder3);
folder1.add(folder4);
//从“Sunny的资料”结点开始进行杀毒操作
folder1.killVirus();
}
}
实例说明
“某软件公司欲开发一个杀毒(Antivirus)软件,该软件既可以对某个文件夹(Folder)杀毒,也可以对某个指定的文件(File)进行杀毒。该杀毒软件还可以根据各类文件的特点,为不同类型的文件提供不同的杀毒方式,例如图像文件(ImageFile)和文本文件(TextFile)的杀毒方式就有所差异。现使用组合模式来设计该杀毒软件的整体框架。
实例类图:
杀毒软件框架设计结构图
实例代码
AbstractFile
:抽象文件类,充当抽象构件类ImageFile
:图像文件类,充当叶子构件类TextFile
:文本文件类,充当叶子构件类VideoFile
:视频文件类,充当叶子构件类Folder
:文件夹类,充当容器构件类Client
:客户端测试类结果及分析
如果需要更换操作节点,例如只对文件夹“文本文件”进行杀毒,客户端代码只需修改一行即可,例如将代码:
folder1.killVirus();
改为:
folder3.killVirus();
在具体实现时,可以创建图形化界面让用户来选择所需操作的根节点,无须修改源代码,符合开闭原则
透明组合模式
安全组合模式
Java AWT中的组件树
模式优点
模式缺点
在增加新构件时很难对容器中的构件类型进行限制
模式适用环境