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

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


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

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

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

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

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

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


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

相关推荐
risc12345633 分钟前
Elasticsearch 线程池
java·大数据·elasticsearch
Linn1 小时前
Spring WebSocket 服务实现的主流方案与最佳实践
spring boot·后端·spring
M1A11 小时前
企业信息化管理(EIM):数字化转型的核心引擎
后端
NE_STOP1 小时前
SpringBoot--如何整体读取多个配置属性及其相关操作
java·spring
apihz2 小时前
通用图片搜索-搜狗源免费API接口使用指南
android·java·python·php·音视频
我是老孙2 小时前
Spring Boot 应用中,配置的加载优先级
spring boot·后端·pycharm
风象南2 小时前
基于 SpringBoot 的 REST API 与 RPC 调用的统一封装
java·spring boot·后端
素雪风华2 小时前
Jenkins+Gitee+Docker容器化部署
java·docker·gitee·jenkins·springboot·持续部署
陈随易2 小时前
Kimi k2不行?一个小技巧,大幅提高一次成型的概率
前端·后端·程序员
暴走的海鸽2 小时前
存储库模式赋能 Django:让你的代码不那么业余,更具生命力
python·设计模式·django