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

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.dtcms.com/a/361092.html

相关文章:

  • Map + 函数式接口的策略模式
  • 控制系统仿真之PID校正-利用PID控制器、PID调节器实现(九)
  • Coze源码分析-工作空间-项目开发-后端源码
  • Python爬虫实战:研究 Lines, bars and markers 模块,构建电商平台数据采集和分析系统
  • 【软件开发工程师の校招秘籍】
  • nginx-realip问题解决方案
  • AI 智能体架构中的协议设计三部曲:MCP → A2A → AG-UI
  • 基于单片机宠物项圈/宠物防丢失设计
  • VMware pro16(许可证)+centos 7超详细安装教程
  • Go语言入门学习笔记
  • 如何将照片从电脑传输到安卓设备
  • GitHub 宕机自救指南:应急解决方案与替代平台
  • LeetCode 165. 比较版本号 - 优雅Java解决方案
  • 【JavaScript】async/await 与 Fetch 传参,PUT,PATCH,文件上传,批量删除等前端案例
  • 《WINDOWS 环境下32位汇编语言程序设计》第10章 内存管理和文件操作(1)
  • 在Lumerical FDTD中,磁偶极子通常用于激发TE模式,而电偶极子用于激发TM模式(文心一言)
  • PyCharm中Debug在状态栏显示运行到光标处(run to cursor)
  • 【MySQL基础】MySQL核心操作全解析
  • 会员店谢幕,补贴战上膛:盒马新十年演绎阿里即时零售战略
  • shell脚本函数介绍
  • (9.1)Python测试之记录
  • 面试 TOP101 动态规划专题题解汇总Java版(BM62 —— BM82)
  • 【数学建模学习笔记】数据标准化
  • NUC029芯片解密和产品应用介绍
  • 玻璃门轻松更换智能密码锁,对接会议预约小程序的方法
  • 美术馆预约小程序|基于微信小程序的美术馆预约平台设计与实现(源码+数据库+文档)
  • Jenkins大总结 20250901
  • 今日分享:C++ -- vector
  • Linux 进程状态 — 僵尸进程
  • keil MDK如何使用第三方软件Keil2Json.exe生成compile_commands.json文件,方便vscode+clangd环境使用