目录
- [一、 啥是组合模式?](#一、 啥是组合模式?)
- [二、 为什么要用组合模式?](#二、 为什么要用组合模式?)
- [三、 组合模式的实现方式](#三、 组合模式的实现方式)
- [四、 组合模式的优缺点](#四、 组合模式的优缺点)
- [五、 组合模式的应用场景](#五、 组合模式的应用场景)
- [六、 总结](#六、 总结)
🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!
🌟了解外观模式请看: (十)趣学设计模式 之 外观模式!
这篇文章带你详细认识一下设计模式中的外观模式
一、 啥是组合模式?
想象一下,你正在整理你的电脑文件 📁。 你有文件,也有文件夹。 文件夹里可以包含文件,也可以包含其他文件夹。 你可以对文件和文件夹进行统一的操作,比如复制、删除、移动等等 ✂️。
组合模式,就是将对象组合成树形结构以表示"整体-部分"的层次结构! 组合模式使得用户对单个对象和组合对象的使用具有一致性 🌳。
简单来说,就是把一组相似的对象组织成树状结构,方便统一管理和操作! 🌲
- 你想表示"整体-部分"的层次结构: 就像文件夹包含文件和文件夹 📁!
- 你想让客户端可以统一地处理单个对象和组合对象: 就像你可以对文件和文件夹进行统一的复制、删除操作 ✂️!
- 你想忽略单个对象和组合对象之间的差异: 就像你不想区分文件和文件夹,都把它们当作"文件系统对象"来处理 📁📄!
二、 为什么要用组合模式?
用组合模式,好处多多 👍:
- 表示层次结构: 可以清晰地表示"整体-部分"的层次结构 🌳!
- 统一操作: 可以统一地操作单个对象和组合对象 ✂️!
- 简化客户端代码: 客户端不需要区分单个对象和组合对象,代码更简洁 🧹!
- 扩展性好: 可以方便地添加新的叶子节点和组合节点 ➕!
三、 组合模式的实现方式
组合模式主要包含以下几个角色:
- Component(组件): 定义组合中叶子节点和组合节点的通用接口。 📁📄 (比如:文件系统对象)
- Leaf(叶子节点): 表示组合中的叶子节点,没有子节点。 📄 (比如:文件)
- Composite(组合节点): 表示组合中的组合节点,可以包含叶子节点和其他组合节点。 📁 (比如:文件夹)
代码示例:
java
import java.util.ArrayList;
import java.util.List;
// 组件:文件系统对象
public abstract class FileSystemObject {
protected String name; // 名称
protected int level = 0; // 层次级别
public FileSystemObject(String name) {
this.name = name;
}
public abstract void display(); // 显示
// 设置层次级别
public void setLevel(int level) {
this.level = level;
}
// 获取缩进字符串
protected String getIndentString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < level; i++) {
sb.append(" "); // 两个空格缩进
}
return sb.toString();
}
}
// 叶子节点:文件
public class File extends FileSystemObject {
public File(String name) {
super(name);
}
@Override
public void display() {
System.out.println(getIndentString() + "文件:" + name);
}
}
// 组合节点:文件夹
public class Directory extends FileSystemObject {
private List<FileSystemObject> children = new ArrayList<>(); // 子节点
public Directory(String name) {
super(name);
}
public void add(FileSystemObject fileSystemObject) {
children.add(fileSystemObject);
}
public void remove(FileSystemObject fileSystemObject) {
children.remove(fileSystemObject);
}
@Override
public void display() {
System.out.println(getIndentString() + "文件夹:" + name);
for (FileSystemObject child : children) {
child.setLevel(this.level + 1); // 设置子节点的层次级别
child.display();
}
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Directory root = new Directory("根目录"); // 创建根目录
Directory dir1 = new Directory("目录1"); // 创建目录1
File file1 = new File("文件1.txt"); // 创建文件1
File file2 = new File("文件2.txt"); // 创建文件2
root.add(dir1); // 将目录1添加到根目录
root.add(file1); // 将文件1添加到根目录
dir1.add(file2); // 将文件2添加到目录1
root.display(); // 显示根目录
}
}
分析:
FileSystemObject
是组件,定义了文件系统对象的通用接口。File
是叶子节点,表示文件。Directory
是组合节点,表示文件夹,可以包含文件和文件夹。
输出结果:
文件夹:根目录
文件夹:目录1
文件:文件2.txt
文件:文件1.txt
四、 组合模式的优缺点
优点:
- 表示层次结构 🌳!
- 统一操作 ✂️!
- 简化客户端代码 🧹!
- 扩展性好 ➕!
缺点:
- 设计较复杂,客户端需要花更多时间理清类之间的层次关系 😫!
- 不容易限制组合中的组件类型,可能会导致运行时错误 💥!
五、 组合模式的应用场景
- 你想表示"整体-部分"的层次结构: 就像文件系统 📁!
- 你想让客户端可以统一地处理单个对象和组合对象: 就像你可以对文件和文件夹进行统一的复制、删除操作 ✂️!
- GUI组件: GUI组件通常是树形结构,比如窗口包含按钮、文本框等组件。
- 组织结构: 公司组织结构可以表示为树形结构,部门包含员工和子部门。
六、 总结
- 组合模式就像把一组相似的对象组织成树状结构,方便统一管理和操作! 🌲
- 主要包含组件、叶子节点和组合节点三个角色! 🎭
- 优点是表示层次结构、统一操作、简化客户端代码、扩展性好! 👍
- 缺点是设计较复杂、不容易限制组合中的组件类型! 👎
- 适用于需要表示"整体-部分"的层次结构,或者需要统一地处理单个对象和组合对象的场景! 🎯
希望这篇文章能让你彻底理解组合模式! 💯 祝你学习愉快! 😄