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

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


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

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

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

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

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

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


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

相关推荐
污领巾24 分钟前
虚幻引擎UE多语言设计与实现
java·数据库·虚幻
sg_knight4 小时前
Spring Cloud LoadBalancer深度解析:官方负载均衡方案迁移指南与避坑实践
java·spring boot·spring·spring cloud·微服务·负载均衡
_何同学5 小时前
Ollama 安装 DeepSeek 与 Spring Boot 集成指南
java·spring boot·后端·ai
Code季风6 小时前
跨语言RPC:使用Java客户端调用Go服务端的HTTP-RPC服务
java·网络协议·http·rpc·golang
盖世英雄酱581367 小时前
时间设置的是23点59分59秒,数据库却存的是第二天00:00:00
java·数据库·后端
爷_7 小时前
Nest.js 最佳实践:异步上下文(Context)实现自动填充
前端·javascript·后端
clmm1237 小时前
Java动态生成Nginx服务配置
java·开发语言·nginx
东方芷兰7 小时前
Leetcode 刷题记录 17 —— 堆
java·c++·b树·算法·leetcode·职场和发展
追逐时光者8 小时前
提高 .NET 编程效率的 Visual Studio 使用技巧和建议!
后端·.net·visual studio
草履虫建模8 小时前
Web开发全栈流程 - Spring boot +Vue 前后端分离
java·前端·vue.js·spring boot·阿里云·elementui·mybatis