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

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


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

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

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

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

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

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


二、套娃工厂的设计图纸(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中点开项目结构树时,请想起组合模式------那个让你优雅处理文件嵌套的隐形套娃师!

相关推荐
weixin_4407841111 小时前
【HandlerThread实现原理】
android·java·开发语言
leoZ23111 小时前
本地跑大模型实战(七):llama.cpp 性能调优,让推理更快更省
java·人工智能·spring·生成对抗网络·语言模型·自然语言处理·llama
有梦不弃11 小时前
模块化单体架构设计方案:DDD + 六边形架构落地实践
后端·架构
mubei-12312 小时前
SpringDAO的用法
java·开发语言·数据库
happymagic12 小时前
java spring boot做的jar包程序,如何实现自动运行启动
java·运维·服务器·spring boot·jar
都叫我大帅哥15 小时前
给 Java 程序员的 CSRF 攻击详解:从原理到防御实战
java
江南十四行15 小时前
Spring框架核心(上)——IoC控制反转与DI依赖注入详解
java·后端·spring
IT_陈寒16 小时前
Redis缓存击穿把我坑惨了,原来这样设过期时间才靠谱
前端·人工智能·后端
fb_1234516 小时前
Linux磁盘分区从入门到实操:MBR_GPT全解析+分区工具实战指南
java·linux·gpt
妙码生花16 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(五十二):管理员权限检查中间件,AI 随意放行预闯大祸
前端·后端·go