代码界的「俄罗斯套娃」:组合模式的嵌套艺术

代码界的「俄罗斯套娃」:组合模式的嵌套艺术


一、当对象开始「装孙子」

你是否见过这样的代码奇观?

文件夹里套着子文件夹,子文件夹又装着文件,文件里存着文件列表...

公司部门包含子部门,子部门管理着团队,团队里又有员工...

游戏技能树的主技能点开是子技能,子技能还能展开更多分支...

组合模式就像代码界的套娃大师------「大的装小的,小的装更小的」,让客户端用同一套姿势盘整个体与组合对象,体验「一即是全,全即是一」的哲学快感。


二、套娃工厂的设计图纸(UML图)

java 复制代码
          ┌─────────────┐  
          │  Component  │  
          ├─────────────┤  
          │ +operation()│  
          │ +add()      │  
          │ +remove()   │  
          └──────△──────┘  
                 │  
        ┌────────┴─────────┐  
        │                  │  
  ┌─────────────┐  ┌─────────────┐  
  │   Leaf      │  │  Composite  │  
  └─────────────┘  ├─────────────┤  
                   │ +children   │  
                   └─────────────┘  
  • 套娃模具(Component):定义统一接口
  • 最小套娃(Leaf):不能再拆分的原子对象
  • 套娃容器(Composite):能装其他套娃的盒子

三、文件系统的套娃表演(代码实战)

1. 定义套娃接口
java 复制代码
// 文件系统元素抽象(所有套娃的模具)  
interface FileSystemComponent {  
    void showDetails(int indent);  
    default void addComponent(FileSystemComponent comp) {  
        throw new UnsupportedOperationException("叶子节点不能装东西!");  
    }  
}  
2. 制造最小套娃(文件)
java 复制代码
class File implements FileSystemComponent {  
    private String name;  
    
    public File(String name) { this.name = name; }  
    
    public void showDetails(int indent) {  
        System.out.println(" ".repeat(indent) + "📄 " + name);  
    }  
}  
3. 制作套娃盒子(文件夹)
java 复制代码
class Folder implements FileSystemComponent {  
    private String name;  
    private List<FileSystemComponent> children = new ArrayList<>();  
    
    public Folder(String name) { this.name = name; }  
    
    public void showDetails(int indent) {  
        System.out.println(" ".repeat(indent) + "📁 " + name);  
        children.forEach(child -> child.showDetails(indent + 2));  
    }  
    
    public void addComponent(FileSystemComponent comp) {  
        children.add(comp);  
    }  
}  
4. 开始套娃表演
java 复制代码
public class MatryoshkaShow {  
    public static void main(String[] args) {  
        // 创建文件系统套娃  
        Folder root = new Folder("我的电脑");  
        
        Folder documents = new Folder("文档");  
        documents.addComponent(new File("简历.doc"));  
        documents.addComponent(new File("账单.xlsx"));  
        
        Folder photos = new Folder("照片");  
        photos.addComponent(new File("毕业照.jpg"));  
        photos.addComponent(new File("团建合影.jpg"));  
        
        root.addComponent(documents);  
        root.addComponent(photos);  
        root.addComponent(new File("readme.txt"));  
        
        // 递归展示套娃结构  
        root.showDetails(0);  
    }  
}  
/* 输出:  
📁 我的电脑  
  📁 文档  
    📄 简历.doc  
    📄 账单.xlsx  
  📁 照片  
    📄 毕业照.jpg  
    📄 团建合影.jpg  
  📄 readme.txt  
*/  

四、套娃 vs 堆积木:组合与聚合的区别

维度 组合模式 普通聚合
统一接口 叶子与容器使用相同接口 容器与内容对象接口不同
递归处理 天然支持递归操作 需要额外处理嵌套结构
客户端视角 无需区分个体与组合 需要判断对象类型
扩展性 容易添加新组件类型 添加新类型影响客户端
现实类比 俄罗斯套娃 乐高积木

五、代码套娃的真实世界

  1. GUI组件树:窗口→面板→按钮→图标
  2. 电商分类系统:大类→子类→商品
  3. 组织结构管理:公司→部门→团队→员工
  4. XML/JSON解析:节点→子节点→属性
  5. 游戏装备系统:背包→盒子→药水

冷知识

Java的Swing框架中,JComponent就是组合模式的典型代表,所有组件都可以嵌套。


六、防套娃翻车指南

  1. 透明性陷阱
java 复制代码
// 错误示范:让文件支持add操作  
File resume = new File("简历.doc");  
resume.addComponent(...); // 抛出异常!  
  1. 循环引用检测
java 复制代码
public void addComponent(FileSystemComponent comp) {  
    if (isAncestor(comp)) {  
        throw new IllegalArgumentException("禁止套娃循环!");  
    }  
    children.add(comp);  
}  
  1. 缓存优化
java 复制代码
// 缓存计算密集型操作(如文件夹大小)  
private long cachedSize;  
public long calculateSize() {  
    if (cachedSize == 0) {  
        cachedSize = children.stream().mapToLong(FileSystemComponent::calculateSize).sum();  
    }  
    return cachedSize;  
}  
  1. 访问者模式联用
java 复制代码
interface FileSystemVisitor {  
    void visitFile(File file);  
    void visitFolder(Folder folder);  
}  

class Folder implements FileSystemComponent {  
    // ...  
    public void accept(FileSystemVisitor visitor) {  
        visitor.visitFolder(this);  
        children.forEach(child -> child.accept(visitor));  
    }  
}  
  1. 安全模式选择
java 复制代码
// 安全模式:拆分Component接口  
interface FileSystemComponent { void showDetails(); }  
interface ContainerComponent extends FileSystemComponent {  
    void addComponent(FileSystemComponent comp);  
}  

七、套娃艺术总结

组合模式让代码成为优雅的嵌套大师:

  • :用于树形结构且需要统一操作的场景
  • :区分透明模式与安全模式
  • 不要:让叶子节点支持容器操作
  • 不要:忽视循环引用的风险

当你在IDE中点开项目结构树时,请想起组合模式------那个让你优雅处理文件嵌套的隐形套娃师!

相关推荐
用户4822137167754 分钟前
C++——访问控制
后端
语落心生14 分钟前
数控技术:数控系统刀补功能的软件实现及其仿真
后端
柯南二号16 分钟前
【Java后端】MyBatis-Plus 原理解析
java·开发语言·mybatis
又是努力搬砖的一年25 分钟前
SpringBoot中,接口加解密
java·spring boot·后端
:-)28 分钟前
idea配置maven国内镜像
java·ide·maven·intellij-idea
ikkkkkkkl32 分钟前
C++设计模式:面向对象设计原则
c++·设计模式·面向对象
0wioiw035 分钟前
Python基础(Flask①)
后端·python·flask
啊阿狸不会拉杆1 小时前
《算法导论》第 27 章 - 多线程算法
java·jvm·c++·算法·图论
用户802973565411 小时前
【水平:编写简单的SpringCloud】用一篇文章精通SpringCloud-1
java
风象南1 小时前
SpringBoot 自研运行时 SQL 调用树,3 分钟定位慢 SQL!
spring boot·后端