设计模式之【组合模式】详解

设计模式——组合模式

一、什么是组合模式

组合模式(Composite Pattern)是一种​​结构型设计模式​​,用于将对象组合成​​树形结构​​以表示"整体-部分"的层次关系。通过让客户端以​​统一的方式处理单个对象和组合对象​​,实现了对树形结构中所有节点的透明化操作。

核心思想:通过共享接口,使得​​叶子节点​​(单个对象)和​​容器节点​​(组合对象)可以被一致对待,客户端无需关心操作的是单个对象还是组合结构。

二、结构组成

组件接口(Component)​​

  • 声明组合对象的统一接口
  • 定义默认行为(如add/remove/getChild等)
  • 可声明访问/管理子组件的接口

​​叶子节点(Leaf)​​

  • 表示组合中的叶子对象(无子节点)
  • 实现组件接口定义的基础操作

​​复合节点(Composite)​​

  • 存储子组件(Leaf或其他Composite)
  • 实现与子组件相关的操作(如添加/删除子节点)
  • 将请求委托给所有子组件

三、应用场景

  • 需要表示​​树形对象结构​​(如文件系统、组织架构)
  • 希望对​​整体和部分使用统一接口​​的场景
  • GUI组件树(如包含子控件的容器控件)
  • 递归处理数据结构(如XML/JSON解析)
  • 数学表达式计算(操作数和操作符的组合)

四、实现

在这里插入图片描述

组件(Component):首先,我们定义一个基础接口 FileComponent,它是所有文件系统组件的基础,无论是文件还是文件夹都需要实现这个接口。

import java.util.ArrayList;
import java.util.List;

interface FileComponent {
    void printPath(String prefix);
}

然后,我们定义两个类:Folder(组合节点) 和 File(叶子节点)。Folder 类是一个组合节点,它可以包含其他 FileComponent 对象;File 类是一个叶子节点,它代表一个单一的文件。

叶子结点:

class File implements FileComponent {
    private String name;

    public File(String name) {
        this.name = name;
    }

    @Override
    public void printPath(String prefix) {
        System.out.println(prefix + "/" + this.name);
    }
}

组合节点:

class Folder implements FileComponent {
    private String name;
    private List<FileComponent> children = new ArrayList<>();

    public Folder(String name) {
        this.name = name;
    }

    public void add(FileComponent component) {
        children.add(component);
    }

    public void remove(FileComponent component) {
        children.remove(component);
    }

    @Override
    public void printPath(String prefix) {
    	// 先打印自己本身
        System.out.println(prefix + "/" + this.name);
        // 再递归打印孩子
        for (FileComponent child : children) {
            child.printPath(prefix + "/" + this.name);
        }
    }
}

最后创建测试类。

public class FileSystemTree {
    public static void main(String[] args) {
        FileComponent root = new Folder("root");
        FileComponent file1 = new File("file1.txt");
        FileComponent subFolder = new Folder("subfolder");
        FileComponent file2 = new File("file2.txt");

        // Add components to the folder structure
        root.add(file1);
        root.add(subFolder);
        subFolder.add(file2);

        // Print the path of each component in the tree
        root.printPath("");
    }
}
// 打印结果
/root
/root/subfolder
/root/subfolder/file2.txt
/root/file1.txt

在这个例子中,FileComponent 接口定义了一个方法 printPath,该方法打印出当前文件或文件夹的路径。Folder 类实现了添加和移除子项的功能,并且递归地打印出所有子文件和子文件夹的路径。File 类简单地打印自己的路径。

五、优缺点分析

优点:

  1. 统一接口:组合模式提供了一致的接口来处理单个对象和组合对象。这意味着客户端代码可以使用相同的接口来操作组件,而不需要知道具体处理的是单个对象还是复合对象。这简化了客户端代码的设计。
  2. 易于扩展:使用组合模式可以很容易地扩展新的组件类型。只要新组件遵守相同的接口,就可以无缝地集成到现有的结构中
  3. 代码复用:组合模式使得代码可以在单个对象和组合对象之间复用,因为它们都实现了相同的接口。
  4. 灵活的层次结构:组合模式非常适合用来表示具有层次关系的对象结构。例如,文件系统、组织结构图等,都可以利用组合模式来表示。
  5. 支持递归操作:由于组合模式中的对象是以树形结构组织的,所以它天然支持递归的操作,比如遍历所有的子节点。
  6. 简化高层模块:高层模块只需要关心Component对象, 而不需要关心它到底是Composite还是Leaf,这使得高层模块更加简洁。

缺点:
能引入不必要的复杂性(特别是在对象层次比较简单的情况下)。以及可能消耗更多的内存。

觉得有帮助的话,点个赞或关注再走呗。

什么是精神内耗?
简单地说,就是心理戏太多,自己消耗自己。
所谓:
言未出,结局已演千百遍;
身未动,心中已过万重山;
行未果,假想灾难愁不展;
事已闭,过往仍在脑中演。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习的小熊猫_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值