结构型:组合模式

发布于:2025-05-23 ⋅ 阅读:(18) ⋅ 点赞:(0)

目录

1、核心思想

2、实现方式

2.1 模式结构

2.2 实现案例

3、优缺点分析

4、适用场景


1、核心思想

目的:将总是在重复、迭代地显示的某种自相似性的结构(部分与整体结构特征相似),例如树形结构,以统一的方式处理单个对象和对象组合,最终达到对象复杂的层次结构与客户端解耦的目的。

解决思路:用组合模式来表达“部分/整体”的层次结构,提取并抽象其相同的部分,特殊化其不同的部分,以提高系统的可复用性与可扩展性,最终达到以不变应万变的目的。

举例

1> 蕨类植物的叶子,不管从哪个层级观察这片叶子,我们都会得到一个固定的结构,这意味着组成植物叶子的部分或整体都有着相同的生长方式。

2> 二叉树,此结构始于其开端的“根”节点,往下分出来两个“枝”节点(左右2个节点)​,接着每个枝节点又可以继续“分枝”​,直至其末端的“叶”节点为止。

2、实现方式

2.1 模式结构

三个核心结构:

  • Component(组件接口)​:所有复合节点与叶节点的高层抽象,定义出需要对组件操作的接口标准(声明管理子组件的方法(如透明模式)或仅定义公共行为(如安全模式))。
  • Composite(复合组件)​:包含多个子组件对象(List<Node>,可以是复合组件或叶端组件)的复合型组件,负责管理子组件(添加、删除、遍历),并委托操作到所有子节点。
  • Leaf(叶端组件)​:不包含子组件的终端组件,同样实现组件接口中定义的操作方法。通常不实现子组件管理方法(如add),若数据接口标准,可抛出异常。

2.2 实现案例

文件系统:文件系统由文件和文件夹构成,文件夹可包含文件或其他文件夹(tree);可以层级打印文件结构(tree)。

// 组件接口
public abstract class Node {
    protect String name;//节点命名

    public Node(String name) {//构造方法需传入节点名
        this.name = name;
    }

    //增加后续子节点方法
    public abstract void add(Node child);

    public void tree(int space) {
        for(int i=0; i < space; i++) {
            System.out.print(" ");//先循环输入space个空格
        }
        System.out.println(name);//接着再输出自己的名字
    }

    //无参重载方法,默认从第0列开始展示
    public void tree() {
        this.tree(0);
    }
}

// 组合:文件夹
class Folder implements Node{
    // 文件夹可以包含子节点(子文件夹或文件)
    private List<Node> children = new ArrayList<>();

    public Folder(String name) { 
        super(name);// 调用父类“节点”的构造方法命名
    }

    public void add(Node child) {
        children.add(child);//可以添加子节点
    }

    @Override
    public void tree() {
        super.tree(space); //调用父类通用的tree方法列出自己的名字
        space++; //在循环的子节点前,空格数要加1
        for (Node child: children) {
            child.tree(); // 调用子节点的tree方法
        }
    }
}

// 叶子:文件
class File implements Node{
    public File(String name)  { 
        super(name);
    }
    public void add(Node child) {
        System.out.println("不能添加子节点");
    }

    @Override
    public void tree() {
        super.tree(space);
    }
}

// 客户端调用
public class Client {
    public static void main(String[] args) {
        Folder root = new Folder("D盘");

        root.add(new File("简历.pdf"));

        Folder subFolder = new Folder("图片");
        subFolder.add(new File("1.jpg"));
        subFolder.add(new File("2.png"));
        root.add(subFolder);

        root.tree();
    }
}

3、优缺点分析

优点:

  • 统一处理:客户端无需区分叶子节点和组合节点。

  • 扩展性强:新增组件类型无需修改现有代码,符合开闭原则。

  • 树形结构支持:天然适合递归和层次化数据管理。

缺点:

  • 接口设计挑战

    • 透明模式:叶子需实现不相关方法(如add),可能抛出异常。

    • 安全模式:客户端需类型检查,失去透明性。

  • 性能开销:递归遍历可能影响性能(深层次结构)。

4、适用场景

  • 树形结构表示:文件系统、菜单/子菜单、组织架构。

  • 递归操作需求:统计目录大小、渲染UI组件树。

  • 统一处理逻辑:对单个对象和组合对象执行相同操作(如复制、删除)。


网站公告

今日签到

点亮在社区的每一天
去签到