当前位置: 首页 > java >正文

99、23种设计模式之组合模式(8/23)

组合模式(Composite Pattern)作为23种经典设计模式之一,属于结构型模式,其核心价值在于统一处理树形结构中的单个对象与组合对象,通过定义一致的接口,使客户端无需区分操作的是叶子节点还是分支节点。

一、组合模式的核心概念

1.适用场景

  • 需要表示“部分-整体”层次结构(如文件系统、UI组件、组织架构)。
  • 希望客户端统一处理单个对象和组合对象,避免冗余的条件判断。
  • 支持递归操作(如遍历树形结构)。

2.核心角色

  • Component(抽象组件):定义叶子节点和分支节点的公共接口,声明管理子节点的方法(如Add、Remove)。
  • Leaf(叶子节点):表示单个对象,无子节点,实现Component接口但抛出异常或空实现管理子节点的方法。
  • Composite(分支节点):包含子节点(叶子或分支),实现Component接口并管理子节点的增删查。

二、C#实现方式

组合模式在C#中有两种典型实现方式,各有优缺点:

1. 透明式组合模式

  • 特点:在Component抽象类中声明所有管理子节点的方法(如Add、Remove),叶子节点和分支节点均实现这些方法(叶子节点抛出异常)。
  • 优点:客户端可一致处理所有节点,无需区分类型。
  • 缺点:叶子节点实现无意义的方法,可能引发运行时异常。
// 抽象组件
public abstract class Component
{public string Name { get; set; }public abstract void Add(Component component);public abstract void Remove(Component component);public abstract void Display(int depth);
}// 叶子节点
public class Leaf : Component
{public Leaf(string name) => Name = name;public override void Add(Component component) => throw new InvalidOperationException("Leaf cannot add components.");public override void Remove(Component component) => throw new InvalidOperationException("Leaf cannot remove components.");public override void Display(int depth) => Console.WriteLine($"{new string('-', depth)}{Name}");
}// 分支节点
public class Composite : Component
{private List<Component> _children = new List<Component>();public Composite(string name) => Name = name;public override void Add(Component component) => _children.Add(component);public override void Remove(Component component) => _children.Remove(component);public override void Display(int depth){Console.WriteLine($"{new string('-', depth)}{Name}");foreach (var child in _children) child.Display(depth + 2);}
}// 客户端代码
var root = new Composite("Root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));
var composite = new Composite("Composite X");
composite.Add(new Leaf("Leaf XA"));
root.Add(composite);
root.Display(1);

2. 安全式组合模式

  • 特点:Component仅声明通用方法(如Display),管理子节点的方法(如Add、Remove)仅在Composite中定义。
  • 优点:避免叶子节点实现无意义方法,类型安全。
  • 缺点:客户端需区分节点类型,破坏透明性。
// 抽象组件(仅声明通用方法)
public abstract class Component
{public string Name { get; set; }public abstract void Display(int depth);
}// 叶子节点
public class Leaf : Component
{public Leaf(string name) => Name = name;public override void Display(int depth) => Console.WriteLine($"{new string('-', depth)}{Name}");
}// 分支节点(声明管理子节点的方法)
public class Composite : Component
{private List<Component> _children = new List<Component>();public Composite(string name) => Name = name;public void Add(Component component) => _children.Add(component);public void Remove(Component component) => _children.Remove(component);public override void Display(int depth){Console.WriteLine($"{new string('-', depth)}{Name}");foreach (var child in _children) child.Display(depth + 2);}
}// 客户端需区分类型调用方法
var composite = new Composite("Composite");
composite.Add(new Leaf("Leaf")); // 合法
var leaf = new Leaf("Leaf");
leaf.Add(new Leaf("Leaf"));     // 编译错误(类型安全)

三、组合模式的优缺点

1.优点

  • 简化客户端代码:统一处理单个对象和组合对象,减少条件判断。
  • 扩展性强:新增组件类型(如新图形)无需修改现有代码,符合开闭原则。
  • 支持递归:方便遍历树形结构(如计算文件夹大小)。

2.缺点

  • 过度使用导致复杂度增加:非层次结构场景强行使用会适得其反。
  • 性能问题:大型树形结构的递归遍历可能引发栈溢出,需优化为迭代或缓存结果。

四、典型应用场景

  • 图形编辑器:基本图形(圆、矩形)与组合图形(由多个基本图形组成)的统一绘制。
  • 文件系统:文件与文件夹的统一操作(如删除、复制)。
  • UI组件:按钮、文本框等控件与窗口的统一管理。
  • 组织架构:员工与部门的统一权限控制。

五、与其他模式的对比

  • 与装饰器模式区别:装饰器模式动态添加职责,组合模式构建树形结构。
  • 与外观模式区别:外观模式简化复杂子系统调用,组合模式统一处理树形结构节点。

在这里插入图片描述

http://www.xdnf.cn/news/19555.html

相关文章:

  • 09.《路由基础知识解析和实践》
  • 基于外部对照数据借用的临床试验统计分析方案设计与仿真研究
  • PitVis-2023挑战赛:内镜下垂体瘤手术视频中的手术流程识别|文献速递-深度学习人工智能医疗图像
  • 如何把指定阿里云文件夹下的所有文件移动到另一个文件夹下,移动文件时把文件名称(不包括文件后缀)进行md5编码
  • 从理论到实践,深入剖析数据库水平拆分的安全平滑落地
  • Spark自定义累加器实现高效WordCount
  • Spark和Spring整合处理离线数据
  • promptoMANIA-AI绘画提示词生成器
  • Electron使用WebAssembly实现CRC-16 CCITT校验
  • macOS中Homebrew安装PHP的详细步骤(五)
  • 深入了解Flink核心:Slot资源管理机制
  • PostgreSQL 索引大全
  • 深入理解Docker容器技术:原理与实践
  • 如何安装CUDA????
  • three.js+WebGL踩坑经验合集(10.1):镜像问题又一坑——THREE.InstancedMesh的正反面显示问题
  • 机器学习-时序预测2
  • 基于FPGA+DSP数据采集处理平台的搭建
  • 【Vue2 ✨】Vue2 入门之旅(四):生命周期钩子
  • Unity核心概念③:Inspector窗口可编辑变量
  • C++/QT day3(9.1)
  • 深度学习中常用的激活函数
  • 关系型数据库——GaussDB的简单学习
  • Spring Boot 和 Spring Cloud 的原理和区别
  • 对于牛客网—语言学习篇—编程初学者入门训练—复合类型:BC141 井字棋及BC142 扫雷题目的解析
  • Composefile配置
  • 瑞芯微RK3576平台FFmpeg硬件编解码移植及性能测试实战攻略
  • 查看LoRA 哪个适配器处于激活状态(67)
  • 单片机元件学习
  • 设计模式:代理模式(Proxy Pattern)
  • 有N个控制点的三次B样条曲线转化为多段三阶Bezier曲线的方法