八、组合模式

  • 目的 : 将对象组合成树形结构以表示"部分-整体"的层次结构。使得用户对单个对象和组合对象的使用具有一致性。
  • 核心 : 定义统一的组件接口(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
相关推荐
无籽西瓜a5 天前
【西瓜带你学设计模式 | 第十三期 - 组合模式】组合模式 —— 树形结构统一处理实现、优缺点与适用场景
java·后端·设计模式·组合模式·软件工程
砍光二叉树13 天前
【设计模式】结构型-组合模式
设计模式·组合模式
bmseven14 天前
23种设计模式 - 组合模式(Composite)
设计模式·组合模式
逆境不可逃2 个月前
【从零入门23种设计模式08】结构型之组合模式(含电商业务场景)
线性代数·算法·设计模式·职场和发展·矩阵·组合模式
短剑重铸之日2 个月前
《设计模式》第九篇:三大类型之结构型模式
java·后端·设计模式·组合模式·代理模式·结构性模式
apolloyhl2 个月前
Composite 组合模式
组合模式
进击的小头2 个月前
创建型模式:组合模式(C语言实现与嵌入式实战)
c语言·开发语言·组合模式
小码过河.3 个月前
设计模式——组合模式
组合模式
茶本无香3 个月前
设计模式之六—组合模式:构建树形结构的艺术
java·设计模式·组合模式