C++ 设计模式之组合模式

news/2024/2/24 8:23:52/文章来源:https://blog.csdn.net/K1_uestc/article/details/135546871

【声明】本题目来源于卡码网(题目页面 (kamacoder.com))

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】


【简介】什么是组合模式

        组合模式是⼀种结构型设计模式,它将对象组合成树状结构来表示“部分-整体”的层次关系。组合模式使得客户端可以统⼀处理单个对象和对象的组合,⽽⽆需区分它们的具体类型。


【基本结构】

组合模式包括下⾯⼏个⻆⾊:

        理解起来⽐较抽象,我们⽤“省份-城市”举个例⼦,省份中包含了多个城市,如果将之⽐喻成⼀个树形结构,城市就是叶⼦节点,它是省份的组成部分,⽽“省份”就是合成节点,可以包含其他城市,形成⼀个整体,省份和城市都是组件,它们都有⼀个共同的操作,⽐如获取信息。

  • Component 组件: 组合模式的“根节点”,定义组合中所有对象的通⽤接⼝,可以是抽象类或接⼝。该类中定义了⼦类的共性内容
  • Leaf 叶⼦:实现了Component接⼝的叶⼦节点,表示组合中的叶⼦对象,叶⼦节点没有⼦节点。
  • Composite 合成: 作⽤是存储⼦部件,并且在Composite中实现了对⼦部件的相关操作,⽐如添加、删除、获取⼦组件等。

        通过组合模式,整个省份的获取信息操作可以⼀次性地执⾏,⽽⽆需关⼼省份中的具体城市。这样就实现了对国家省份和城市的管理和操作。


 【简易实现】

        利用Java代码作以说明:

1. 组件接口

// 组件接⼝
interface Component {void operation();
}

2. 叶子节点

// 叶⼦节点
class Leaf implements Component {@Overridepublic void operation() {System.out.println("Leaf operation");}
}

3. 组合节点

// 组合节点:包含叶⼦节点的操作⾏为
class Composite implements Component {private List<Component> components = new ArrayList<>();public void add(Component component) {components.add(component);}public void remove(Component component) {components.remove(component);}@Overridepublic void operation() {System.out.println("Composite operation");for (Component component : components) {component.operation();}}
}

4. 客户端代码

// 客户端代码
public class Client {public static void main(String[] args) {// 创建叶⼦节点Leaf leaf = new Leaf();// 创建组合节点,并添加叶⼦节点Composite composite = new Composite();composite.add(leaf);composite.operation(); // 统⼀调⽤}
}

【使用场景】

        组合模式可以使得客户端可以统⼀处理单个对象和组合对象,⽆需区分它们之间的差异,⽐如在图形编辑器中,图形对象可以是简单的线、圆形,也可以是复杂的组合图形,这个时候可以对组合节点添加统⼀的操作。
        总的来说,组合模式适⽤于任何需要构建具有部分-整体层次结构的场景,⽐如组织架构管理、⽂件系统的⽂件和⽂件夹组织等。


【C++ 编码部分】

1. 题目描述

        小明所在的公司内部有多个部门,每个部门下可能有不同的子部门或者员工。请你设计一个组合模式来管理这些部门和员工,实现对公司组织结构的统一操作。部门和员工都具有一个通用的接口,可以获取他们的名称以及展示公司组织结构。

2. 输入描述

        第一行是一个整数 N(1 <= N <= 100),表示后面有 N 行输入。 接下来的 N 行,每行描述一个部门或员工的信息。部门的信息格式为 D 部门名称,员工的信息格式为 E 员工名称,其中 D 或 E 表示部门或员工。

3. 输出描述

        输出公司的组织结构,展示每个部门下的子部门和员工。

4. C++ 编码实例

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file CompositeMode.hpp
* @brief 组合模式
* @autor 写代码的小恐龙er
* @date 2024/01/12
*/#include <iostream>
#include <string>
#include <vector>using namespace std;
// 前置声明
// Component 组件: 组合模式的“根节点”,定义组合中所有对象的通⽤接⼝,可以是抽象类或接⼝
class Component;// 叶⼦节点1 -- 部门 (还可以包含子部门和员工)
class Department;
// 叶子节点2 -- 员工
class Employee;// 组合节点 -- 包含叶子节点的操作行为
class Composite;// Component 组件: 组合模式的“根节点”
class Component
{
public:// 提供信息展示的公共接口virtual void ShowInfo(int depth) = 0;
};// 叶⼦节点1 -- 部门 (还可以包含子部门和员工)
class Department : public Component
{
// 成员属性
private:// 部门名称string _name; // 子部门 -- 新建子部门的室友  使用派生类来新建 基类std::vector<Component *> _childrenVec; //成员函数
public:// 重载构造函数 以便通过部门名称新建部门Department(){}Department(string name){this->_name = name;}// 添加子部门void AddSubDepartment(Component * component){_childrenVec.push_back(component);}// 重载部门信息展示函数void ShowInfo(int depth) override {// ======= 展示自己的信息 =======string info = "";for(int i = 0; i < depth; i++){info += "  ";}std::cout << info << _name << endl;// ======= 展示子部门的信息 =======for(int j = 0; j < _childrenVec.size(); j++){_childrenVec[j]->ShowInfo(depth + 1);}}};// 叶子节点2 -- 员工
class Employee : public Component
{
// 成员属性
private:// 员工名称string _name; //成员函数
public:// 重载构造函数 以便通过员工名称新建员工Employee(string name){this->_name = name;}// 重载员工信息展示函数void ShowInfo(int depth) override {// ======= 展示自己的信息 =======string info = "";for(int i = 0; i < depth; i++){info += "  ";}std::cout << info << "  " << _name << endl;}
};// 组合节点 -- 包含叶子节点的操作行为
class Composite
{
// 成员属性
private:// 公司名称 -- 管理这些叶子节点的 根节点string _name;// 根节点Department *_rootDepartment;// 成员函数
public:// 重载构造函数 来新建某个公司Composite(string name){this->_name = name;_rootDepartment = new Department(name);}// 析构函数~Composite(){if(_rootDepartment != nullptr){delete _rootDepartment;_rootDepartment = nullptr;}}// 添加根节点下面的子节点void AddComponent(Component *component){_rootDepartment->AddSubDepartment(component);}// 信息展示初始函数 void ShowInfo(){std::cout << "Company Structure:" << endl;// 此时开头的根节点 不需要做缩进 故而 参数传入0_rootDepartment->ShowInfo(0);}
};int  main()
{// 公司名称string companyName = "";//输入std::cin >> companyName;// 部门和员工总数int number = 0;// 输入std::cin >> number;// 组合节点 -- 传入公司名称 新建根节点Composite *company = new Composite(companyName);for(int i = 0; i < number; i++){// 信息类型char type = ' ';// 名称 string name = "";// 输入std::cin >> type >> name;// 新建部门 -- 名称构造Component *component = nullptr;Employee *employee = nullptr;if(type == 'D'){// 新建部门派生类Component *component = new Department(name);company->AddComponent(component);}else if(type == 'E'){// 新建员工派生类Component *employee = new Employee(name);company->AddComponent(employee);}else continue;// 析构掉New出来的内存if(component != nullptr) {delete component;component = nullptr;}if(component != nullptr) {delete employee;employee = nullptr;}}// 添加完根节点和子节点后开始结构信息展示company->ShowInfo();// 析构掉New出来的内存delete company;company = nullptr;return 0;
}


......

To be continued.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_925479.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动化神器 Playwright 的 Web 自动化测试解决方案

1. 主流框架的认识 总结&#xff1a; 由于Selenium在3.x和4.x两个版本的迭代中并没有发生多大的变化&#xff0c;因此Selenium一统天下的地位可能因新框架的出现而变得不那么稳固。后续的Cypress、TestCafe、Puppeteer被誉为后Selenium时代Web UI自动化的三驾马车。但是由于这三…

ES数据聚合

1.数据聚合 聚合&#xff08;aggregations&#xff09;可以让我们极其方便的实现对数据的统计、分析、运算。例如&#xff1a; 什么品牌的手机最受欢迎&#xff1f; 这些手机的平均价格、最高价格、最低价格&#xff1f; 这些手机每月的销售情况如何&#xff1f; 实现这些…

Python办公自动化 – 自动化文本翻译和Oracle数据库操作

Python办公自动化 – 自动化文本翻译和Oracle数据库操作 以下是往期的文章目录&#xff0c;需要可以查看哦。 Python办公自动化 – Excel和Word的操作运用 Python办公自动化 – Python发送电子邮件和Outlook的集成 Python办公自动化 – 对PDF文档和PPT文档的处理 Python办公自…

Smallpdf扫描、转换、压缩、编辑、签名PDF

【应用名称】&#xff1a;Smallpdf: 扫描、转换、压缩、编辑、签名PDF 【适用平台】&#xff1a;#Android 【软件标签】&#xff1a;#Smallpdf 【应用版本】&#xff1a;1.71.0 【应用大小】&#xff1a;150MB 【软件说明】&#xff1a;通过 Smallpdf&#xff0c;您可以&…

【河海大学论文LaTeX+VSCode全指南】

河海大学论文LaTeXVSCode全指南 前言一、 LaTeX \LaTeX{} LATE​X的安装二、VScode的安装三、VScode的配置四、验证五、优化 前言 LaTeX \LaTeX{} LATE​X在论文写作方面具有传统Word无法比拟的优点&#xff0c;VScode作为一个轻量化的全功能文本编辑器&#xff0c;由于其极强的…

Python 二维平面Delaunay三角网建立

目录 一、算法概念二、代码实现三、结果示例根据二维平面内的离散点建立平面三角网。 一、算法概念 三角剖分与Delaunay剖分定义:如何把一个散点集剖分成不均匀的三角形网格,即在给定的平面点集上,生成三角形集合的过程。考虑平面点集P={p1,p2,p3,…,pn},我们希望得到三…

Kibana:使用反向地理编码绘制自定义区域地图

Elastic 地图&#xff08;Maps&#xff09;附带预定义区域&#xff0c;可让你通过指标快速可视化区域。 地图还提供了绘制你自己的区域地图的功能。 你可以使用任何您想要的区域数据&#xff0c;只要你的源数据包含相应区域的标识符即可。 但是&#xff0c;当源数据不包含区域…

前端安全专题

xss (Cross Site Scripting) 跨站脚本攻击 原理 通常指黑客通过"HTML注入"篡改了网页&#xff0c;插入了恶意的脚本&#xff0c;从而在用户浏览网页时&#xff0c;控制用户浏览器的一种攻击。 常见攻击类型 存储型XSS 攻击者将恶意的 JavaScript 脚本存储在网站…

模板设计模式-实例

在软件开发中&#xff0c;有时也会遇到类似的情况&#xff0c;某个方法的实现需要多个步骤&#xff08;类似“请客”&#xff09;&#xff0c;其 中有些步骤是固定的&#xff08;类似“点单”和“买单”&#xff09;&#xff0c;而有些步骤并不固定&#xff0c;存在可变性&…

redis之单线程和多线程

目录 1、redis的发展史 2、redis为什么选择单线程&#xff1f; 3、主线程和Io线程是怎么协作完成请求处理的&#xff1f; 4、IO多路复用 5、开启redis多线程 1、redis的发展史 Redis4.0之前是用的单线程&#xff0c;4.0以后逐渐支持多线程 Redis4.0之前一直采用单线程的主…

【GitHub项目推荐--一行命令下载全网视频】【转载】

项目地址&#xff1a;https://github.com/soimort/you-get 首先声明&#xff0c;请不要使用该项目从事违法活动哦~仅供学习使用&#xff01; 解决痛点 如果你上网的时候看了一些东西不错&#xff0c;想下载下来&#xff0c;或者在线观看喜欢的视频&#xff0c;但是没有找到网…

Android Studio 如何设置中文

Android Studio 是一个为 Adndroid 平台开发程序的集成开发环境&#xff08;IDE&#xff09;。 如何安装中文插件 在 Jetbrains 家族的插件市场上&#xff0c;是能够搜到语言包插件的&#xff0c;正常情况下安装之后只需要重启即可享受中文界面&#xff0c;可AndroidStudio 中…

物联网介绍

阅读引言&#xff1a; 本文从多方面叙述物联网的定义以及在物联网当中的各种通信的介绍。 一、物联网的定义 1.1 通用的定义 物联网&#xff08;Internet of Things&#xff0c;IOT&#xff1b;也称为Web of Things&#xff09;是指通过各种信息传感设 备&#xff0c;如传感器、…

Vue3-TS中的接口-泛型-自定义类型

1首先一般在src下新建types文件夹&#xff0c;用来存放接口类型 2定义一个接口&#xff0c;用于限制person对象的具体属性 当需要用这个类型形成数组时&#xff0c;有2种写法 export type Persons Array<PersonInter> export type Persons PersonInter[] 3在文件中使…

【目标跟踪】跨相机如何匹配像素

文章目录 前言一、计算思路二、代码三、结果 前言 本本篇博客介绍一种非常简单粗暴的方法&#xff0c;做到跨相机像素匹配。已知各相机内外参&#xff0c;计算共视区域像素投影&#xff08;不需要计算图像特征&#xff09;。废话不多说&#xff0c;直接来&#xff0c;见下图。…

C#--核心

CSharp核心知识点学习 学习内容有&#xff1a; 绪论&#xff1a;面向对象的概念 Lesson1&#xff1a;类和对象 练习&#xff1a; Lesson2&#xff1a;封装--成员变量和访问修饰符 练习: Lesson3:封装--成员方法 Lesson4&#xff1a;封装--构造函数和析构函数 知识点四 垃圾回收…

git主分支合并到本地分支起冲突的解决办法

1.原因&#xff1a;一个项目几个人共同承担&#xff0c;难免有交叉的部分&#xff0c;这个时候交叉部分的提交就会导致冲突 2.方法&#xff1a;点开该类手动进行更改&#xff1a; 一般会有两种情况&#xff1a;一个是更改&#xff0c;一个是冲突(IDEA右上角会显示)&#xff1b;…

meter报OOM错误,如何解决?

根据在之前的压测过程碰到的问题&#xff0c;今天稍微总结总结&#xff0c;以后方便自己查找。 一、单台Mac进行压测时候&#xff0c;压测客户端Jmeter启动超过2000个线程&#xff0c;Jmeter报OOM错误&#xff0c;如何解决&#xff1f; 解答&#xff1a;单台Mac配置内存为8G&…

详解java中ArrayList

目录 前言 一、ArrayList是什么 二、ArrayList使用 1、ArrayList的构造 2 、ArrayList常见操作 3、 ArrayList的遍历 4、 ArrayList的扩容机制 三、来个练习 前言 当你看到这篇文章我觉得很好笑&#xff0c;因为我开始也不懂ArrayList现在轮到你了&#xff0c;嘻嘻嘻&am…

GRE隧道(初级VPN)配置步骤

一、拓朴图&#xff1a; 要求&#xff1a;1、PC1 和 PC2 能访问充当互联网接口地址的ISP环回口地址8.8.8.8 2、PC1 和 PC2 走GRE隧道互通 二、配置步骤&#xff1a; 1、配置IP 2、R1、R2 配置nat&#xff0c;代理内网地址通过G0/0/0口上外网 acl 2000rule permit source a…