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

5.组合模式

目录

  • 一、概念
  • 二、类图详解
  • 三、组合模式实现步骤
  • 四、代码实现
    • 4.1 Component类
    • 4.2 Composite类
    • 4.3 Leaf类
    • 4.4 测试
  • 五、扩展

一、概念

  • 组合模式又叫整体--部分模式
  • 组合模式描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无须对它们进行区分
  • 可以一致地对待容器对象和叶子对象。
  • 它使树型结构的问题中,模糊了简单元素复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

二、类图详解

在这里插入图片描述

  • 包含一个抽象组件类Component、叶子结点类Leaf和组件集合类Composite
  • 抽象组件类:组合中的对象声明接口,实现所有类共有接口的行为。声明用于访问和管理Component的子部件的接口。
  • 叶子结点:叶节点对象,就是终端独立结点,不能addRemove其它组件。
  • 组件集合类:实现Component的相关操作,可以继续包含组件集合类和叶子结点。
  • CompositeComponent类形成迭代关联关系。

三、组合模式实现步骤

  • 定义抽象组件接口
  • 实现叶子节点类,实现抽象组件类的接口。
  • 实现组件集合类,实现抽象组件类的接口。
  • 定义环境类,将叶子节点和组件集合加入根组件集合。

四、代码实现

  • 生成目录树结构,目录里面可以再放目录或文件
  • 最终的输出如下
    在这里插入图片描述

4.1 Component类

  • 顶层接口
#pragma once
#include <iostream>class Component
{
public:std::string name;  //叶子结点和组件结点都有名字和类型bool m_isLeaf;     //是否是叶子结点(暂时没用)Component(const std::string& name, bool isLeaf){this->name = name;this->m_isLeaf = isLeaf;}virtual void Add(Component* c) = 0;virtual void Remove(Component* c) = 0;virtual void Display(int depth) = 0;bool isLeaf() const{return this->m_isLeaf;}
};

4.2 Composite类

  • 用来放文件夹或文件
#pragma once
#include <iostream>
#include <list>#include "Component.h"class Composite: public Component
{
private:std::list<Component*> m_component;public:Composite(const std::string& name) : Component(name, false){}void Add(Component* c) override{m_component.push_back(c);}void Remove(Component* c) override{m_component.remove(c);}void Display(int depth) override{std::cout << std::string(depth, '-') << name << std::endl;for (auto item : m_component){item->Display(depth + 2);}}
};

4.3 Leaf类

  • 用来放文件
#pragma once
#include <iostream>
#include "Component.h"class Leaf: public Component
{
public:Leaf(const std::string& name): Component(name, true){}void Add(Component* c) override{std::cout << "Can't add component to leaf." << std::endl;}void Remove(Component* c) override{std::cout << "Can't remove component to leaf." << std::endl;}void Display(int depth) override{std::cout << std::string(depth, '-') << name << std::endl;}
};

4.4 测试

#include "Leaf.h"
#include "Composite.h"class Client
{
private:Component* com;public:Client(Component* obj){com = obj;}void display(int n){com->Display(n);}
};int main()
{Component* root = new Composite("根目录");root->Add(new Leaf("根目录下的文件A"));root->Add(new Leaf("根目录下的文件B"));Component* dir1 = new Composite("根目录下的文件夹FA");dir1->Add(new Leaf("文件夹FA下的文件A"));dir1->Add(new Leaf("文件夹FA下的文件B"));root->Add(dir1);Component* dir2 = new Composite("根目录FA下的文件夹FAX");dir2->Add(new Leaf("文件夹FAX下的文件A"));dir2->Add(new Leaf("文件夹FAX下的文件B"));dir1->Add(dir2);root->Add(new Leaf("根目录下的文件C"));root->Add(new Leaf("根目录下的文件D"));Client c(root);c.display(1);return 0;
}

五、扩展

  • 设计一个饭店的菜单
  • 可以再包含一个菜单或者菜单项
  • 类图如下
    在这里插入图片描述
  • 菜单项图结构如下
    在这里插入图片描述
  • 代码部分请参阅 https://gitee.com/piglittle/design_patterns中的 Head_First_Design_Partterns解决方案下的 composite_pattern项目
http://www.lryc.cn/news/593480.html

相关文章:

  • 3.5软件开发活动[2-系统设计]面向对象设计-UML统一开发过程
  • [故障诊断方向]SNNs:针对小样本轴承故障诊断的孪生神经网络模型
  • 在Vscode中使用Kimi K2模型:实践指南,三分钟生成个小游戏
  • 练习三:熟知前端知识
  • 目标检测中的标签分配算法总结
  • MinIO深度解析:从核心特性到Spring Boot实战集成
  • Vue的路由模式的区别和原理
  • 《Qt5串口开发》搭建跨平台通信系统
  • VSCode用Python操作MySQL:环境配置与代码验证
  • 操作系统-分布式同步
  • 实验室危险品智能管控:行为识别算法降低爆炸风险
  • Mybatis学习之简介(一)
  • Vue 3 中封装并使用 IndexedDB 的完整教程(含泛型、模块化、通用 CRUD)
  • Vue Swiper组件
  • 93.数字信号处理相关的一些问题
  • 单元测试学习+AI辅助单测
  • 【ArcGIS技巧】最近分享的GIS插件总结与优化
  • Spring MVC源码分析 DispatcherServlet#getHandlerAdapter方法
  • LVS四种工作模式深度解析
  • Go 语言核心机制深度剖析:指针、defer、多态与空接口实战指南
  • 使用 go-redis-entraid 实现 Entra ID 无密钥认证
  • Go-Redis × RediSearch 全流程实践
  • leetcode_121 买卖股票的最佳时期
  • 力扣经典算法篇-26-长度最小的子数组(暴力求解法,左右指针法)
  • 【Java】【力扣】48.旋转图像
  • FPGA自学——整体设计思路
  • Redis数据库基础与持久化部署
  • 使用CCS6.2为C2000(DSP28335)生成.bin文件和.hex文件
  • 【LeetCode 热题 100】437. 路径总和 III——(解法一)递归递归!
  • CCF编程能力等级认证GESP—C++7级—20250628