- 目的 : 将对象组合成树形结构以表示"部分-整体"的层次结构。使得用户对单个对象和组合对象的使用具有一致性。
- 核心 : 定义统一的组件接口(Component),叶子节点(Leaf)实现基本操作,容器节点(Composite)包含子组件并管理它们(添加、删除、遍历)。
- 场景 : 常用于构建树形结构,如文件系统、菜单系统等。
函数入口
java
package composite;
import java.util.List;
/*
组合模式演示 - 入口函数
展示树形结构的构建和遍历
*/
public class Main {
public static void main(String[] args) {
// 构建文件系统结构
demonstrateFileSystem();
}
// 文件系统结构
private static void demonstrateFileSystem() {
System.out.println("\n--- 文件系统结构 ---");
// 创建文件系统树
Tree fileSystem = new Tree("D:");
// 获取根节点
TreeNode root = fileSystem.getRoot();
// 创建目录和文件
TreeNode programFiles = new TreeNode("Program Files");
TreeNode users = new TreeNode("Users");
TreeNode windows = new TreeNode("Windows");
// 向Program Files添加子节点
TreeNode javaDir = new TreeNode("Java");
javaDir.add(new TreeNode("jdk1.8.0"));
programFiles.add(javaDir);
// 向Users添加子节点
TreeNode userJohn = new TreeNode("John");
userJohn.add(new TreeNode("Music"));
users.add(userJohn);
TreeNode userAlice = new TreeNode("Alice");
userAlice.add(new TreeNode("Pictures"));
users.add(userAlice);
// 向Windows添加子节点
windows.add(new TreeNode("System64"));
// 将所有目录添加到根节点
root.add(programFiles);
root.add(users);
root.add(windows);
// 打印文件系统结构
printTreeStructure(fileSystem.getRoot());
}
// 打印树形结构
private static void printTreeStructure(TreeNode root) {
if (root == null) {
System.out.println("空树");
return;
}
printTreeNode(root, 0);
}
// 递归打印节点
private static void printTreeNode(TreeNode node, int depth) {
String indent = buildIndent(depth);
String nodeType = node.isLeaf() ? "📄" : "📁"; // 使用图标区分类型
String prefix = node.isRoot() ? "🏠 " : " ";
System.out.println(indent + prefix + nodeType + " " + node.getName());
List<TreeNode> children = node.getChildren();
for (TreeNode child : children) {
printTreeNode(child, depth + 1);
}
}
// 构建缩进字符串
private static String buildIndent(int depth) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) {
sb.append(" ");
}
return sb.toString();
}
List<TreeNode> children = node.getChildren();
for (TreeNode child : children) {
printTreeNode(child, depth + 1);
}
}
// 构建缩进字符串
private static String buildIndent(int depth) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) {
sb.append(" ");
}
return sb.toString();
}
}
然后是树节点类 - 组合模式中的Component
同时充当Leaf和Composite的角色:
当没有子节点时,作为Leaf;当有子节点时,作为Composite
java
package composite;
import java.util.ArrayList;
import java.util.List;
public class TreeNode {
private String name; // 节点名称
private TreeNode parent; // 父节点引用
private List<TreeNode> children; // 子节点列表
public TreeNode(String name) {
this.name = name;
this.children = new ArrayList<>(); // 初始化子节点列表
}
// ========== Getter和Setter方法 ==========
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setParent(TreeNode parent) {
this.parent = parent;
}
public TreeNode getParent() {
return this.parent;
}
// 获取子节点列表(返回不可修改的列表以保证封装性)
public List<TreeNode> getChildren() {
return new ArrayList<>(this.children); // 返回副本保护内部数据
}
// ========== 组合模式的核心操作 ==========
// 添加子节点
public void add(TreeNode node) {
if (node == null) {
throw new IllegalArgumentException("不能添加空节点");
}
if (node == this) {
throw new IllegalArgumentException("不能添加自身作为子节点");
}
this.children.add(node);
node.setParent(this); // 设置子节点的父节点为当前节点
}
// 移除子节点
public void remove(TreeNode node) {
if (node != null && this.children.remove(node)) {
node.setParent(null); // 清除被移除节点的父节点引用
}
}
// 判断是否为叶子节点(没有子节点)
public boolean isLeaf() {
return this.children.isEmpty();
}
// 判断是否为根节点(没有父节点)
public boolean isRoot() {
return this.parent == null;
}
}
最后是树类 - 组合模式的客户端使用类
封装了对树形结构的整体操作,提供更友好的API
java
package composite;
public class Tree {
private TreeNode root; // 根节点
public Tree(String name) {
this.root = new TreeNode(name);
}
// 获取根节点
public TreeNode getRoot() {
return root;
}
}
会打印:
--- 文件系统结构 ---
🏠 📁 D:
📁 Program Files
📁 Java
📄 jdk1.8.0
📁 Users
📁 John
📄 Music
📁 Alice
📄 Pictures
📁 Windows
📄 System64
