结构型设计模式之组合模式【设计模式系列】

系列文章目录

C++技能系列
Linux通信架构系列
C++高性能优化编程系列
深入理解软件架构设计系列
高级C++并发线程编程
设计模式系列

期待你的关注哦!!!
在这里插入图片描述

现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。
Now everything is for the future of dream weaving wings, let the dream fly in reality.

结构型设计模式之组合模式

  • 系列文章目录
  • 一、组合模式介绍
  • 二、组合模式优缺点
    • 2.1 优点
    • 2.2 缺点
  • 三、组合模式使用场景
  • 四、组合模式实现

一、组合模式介绍

⚠️ 意图:
将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

⚠️ 主要解决:
它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

⚠️ 何时使用:
1、您想表示对象的部分-整体层次结构(树形结构)。 2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

⚠️ 如何解决:
树枝和叶子实现统一接口,树枝内部组合该接口。

现有一个公司需要实现一个广播的功能,用来通知给公司所有部门重要的信息。如果需要广播,那么必须通过每一个部门类的实例去调用各自部门的广播接口。通过一个抽象类来抽象出广播接口,各个部门和公司都通过继承实现抽象接口。如此实现可以将所有部门放在一个容器内,遍历实现其广播接口。如果公司不扩大,永远有这几个部门并且没有分公司的话,是没问题的。如果再要添加一个部门,就必须实现一个部门类,再修改总公司类。这明显违背了开闭原则。既然我们通过抽象类来实现了其方法,那就可以实现抽象的增加,删除,查询接口。如此一来,如果要有新的部门, 那么只需要通过调用添加接口来增加新部门, 广播的时候,只需要遍历容器中的广播接口即可。实现类图如下:

在这里插入图片描述

图1_1 组合模式类图

组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。掌握组合模式的重点是要理解清楚 “部分/整体” 还有 ”单个对象“ 与 “组合对象” 的含义。

组合模式可以让客户端像修改配置文件一样简单的完成本来需要流程控制语句来完成的功能。

二、组合模式优缺点

2.1 优点

  • 简化客户端调用,实现符合开闭原则。
  • 高层模块调用简单。
  • 节点自由增加

2.2 缺点

  • 如果业务逻辑负责,则实现组合模式比较困难。

  • 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。

三、组合模式使用场景

适用于“整体-部分”层次的树形结构的。部分、整体场景,如树形菜单,文件、文件夹的管理。

客户端对组合对象统一的使用所有对象。

四、组合模式实现

Component.h

#ifndef COMPONENTS_H_
#define COMPONENTS_H_#include <iostream>
#include <vector>using namespace std;class Components
{
public:Components(std::string strName):m_strName(strName){}virtual void Operation() = 0;virtual void AddSubCompany(Components* subCompany);virtual void DelSubCompany(Components* subCompany);virtual Components* GetCompanyByIndex(int iIndex);protected:std::string m_strName;
};class ConcreteCompany : public Components
{
public:ConcreteCompany(std::string strName):Components(strName){}~ConcreteCompany();virtual void Operation();virtual void AddSubCompany(Components* subCompany);virtual void DelSubCompany(Components* subCompany);virtual Components* GetCompanyByIndex(int iIndex);
private:std::vector<Components*> m_vecSubItem;
};class FinanceDepartment : public Components
{
public:FinanceDepartment(std::string strName):Components(strName){}virtual void Operation();
};class HRDepartment : public Components
{
public:HRDepartment(std::string strName):Components(strName){}virtual void Operation();
};#endif

Component.cpp

#include "Company.h"
#include <algorithm>#ifndef SAFE_DELETE
#define SAFE_DELETE(p){if((p) != NULL){delete (p); (p) = NULL;}}
#endifvoid Components::AddSubCompany( Components* subCompany )
{cout << "Have no realized!" << endl;
}void Components::DelSubCompany( Components* subCompany )
{cout << "Have no realized!" << endl;
}Components* Components::GetCompanyByIndex( int iIndex )
{cout << "Have no realized!" << endl;return NULL;
}//******************//
//**CentralCompany**//
//******************//ConcreteCompany::~ConcreteCompany()
{std::for_each(m_vecSubItem.begin(),m_vecSubItem.end(),[&](Components* item){SAFE_DELETE(item);});
}void ConcreteCompany::Operation()
{std::for_each(m_vecSubItem.begin(),m_vecSubItem.end(),[&](Components* item){item->Operation();});
}void ConcreteCompany::AddSubCompany( Components* subCompany )
{if (subCompany != NULL){m_vecSubItem.push_back(subCompany);}
}void ConcreteCompany::DelSubCompany( Components* subCompany )
{for (auto it = m_vecSubItem.begin(); it != m_vecSubItem.end(); ++it){if ((*it) == subCompany){m_vecSubItem.erase(it);SAFE_DELETE(subCompany);break;}}
}Components* ConcreteCompany::GetCompanyByIndex( int iIndex )
{if (iIndex < 0 || iIndex > m_vecSubItem.size()){return NULL;}return m_vecSubItem[iIndex];
}void FinanceDepartment::Operation()
{cout << m_strName.c_str() << endl;
}void HRDepartment::Operation()
{cout << m_strName.c_str() << endl;
}

main.cpp

#include <iostream>
#include "Company.h"using namespace std;int main()
{Components* Central = new ConcreteCompany("Central Company");Central->AddSubCompany(new FinanceDepartment("Central Finance Department"));Central->AddSubCompany(new HRDepartment("Central HR Department"));Components* Xian = new ConcreteCompany("Xi'An Company");Xian->AddSubCompany(new FinanceDepartment("Xi'An Finance Department"));Xian->AddSubCompany(new HRDepartment("Xi'An HR Department"));Central->AddSubCompany(Xian);Central->Operation();cout << "<<<<<>>>>>" << endl;Central->DelSubCompany(Xian);Central->Operation();return 0;
}

输出:

Central Finance DepartmentCentral HR DepartmentXi’An Finance DepartmentXi’An HR Department<<<<<>>>>>Central Finance DepartmentCentral HR Department

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

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

相关文章

Hadoop学习日记-MapReduce思想及执行流程

MapReduce思想 Map负责“拆分”&#xff1a;即将复杂问题拆分成可以并行计算的小问题&#xff0c;彼此之间几乎没有依赖联系。 Reduce负责对Map阶段的结果进行合并汇总 Map和Reduce的抽象接口如下&#xff1a; map:(k1; v1) — (k2; v2) reduce:(k2; [v2]) — (k3; v3) 一…

看了2023年的一线互联网公司时薪排行榜!值得思考

前言 根据最近针对国内的一线互联网企业做的调研&#xff0c;汇总了他们的平均时薪水平&#xff0c;最终出了一个排行榜&#xff01; 首先我们来看下&#xff0c;排行榜分哪几个Level&#xff0c;分别为初级、中级、高级、资深、专家/架构这五个&#xff0c;主要根据工程师的…

基于Javaweb实现ATM机系统开发实战(十四)交易记录分页实现

还是老规矩&#xff0c;先看前端页面查看需要传递哪些参数&#xff0c;并且把逻辑有问题的部分进行修改~ <% page language"java" contentType"text/html; charsetUTF-8" pageEncoding"UTF-8"%> <% taglib prefix"c" uri&qu…

自然语言处理14-基于文本向量和欧氏距离相似度的文本匹配,用于找到与查询语句最相似的文本

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下自然语言处理14-基于文本向量和欧氏距离相似度的文本匹配&#xff0c;用于找到与查询语句最相似的文本。NLP中的文本匹配是指通过计算文本之间的相似度来找到与查询语句最相似的文本。其中一种常用的方法是基于文本…

AcrelEMS企业微电网能效管理平台实现用户侧智能配电和智能用电管理-安科瑞黄安南

摘要&#xff1a;随着科技的发展&#xff0c;电力系统正逐步向智能化、数字化、互联网化迈进。智能配电与智能用电是电力产业发展的重要方向&#xff0c;将为传统电力系统带来革命性的变革。本文将对智能配电和智能用电的概念、特点、关键技术及应用进行详细介绍。 1、智能配电…

数据结构初阶--带头双向循环链表

目录 一.带头双向循环链表的定义 二.带头双向循环链表的功能实现 2.1.带头双向循环链表的定义 2.2.带头双向循环链表的结点创建 2.3.带头双向循环链表的初始化 2.4.带头双向循环链表的打印 2.5.带头双向循环链表的判空 2.6.带头双向循环链表的尾插 2.7.带头双向循环链…

白皮书|数字孪生工厂:成就智能制造的未来

前言 目前我国已经进入“技术应用”的数字孪生双驱动时代&#xff0c;在市场需求和国家政策的推动下&#xff0c;各地因地制宜发展数字孪生技术&#xff0c;深入开展数字孪生应用建设。今天我们就重点来聊一聊数字孪生技术在工厂中的应用&#xff0c;希望通过本次案例的深度剖析…

深“扒”云原生高性能分布式文件系统JuiceFS

JuiceFS 是一款面向云原生设计的高性能分布式文件系统&#xff0c;在 Apache 2.0 开源协议下发布。提供完备的 POSIX 兼容性&#xff0c;可将几乎所有对象存储接入本地作为海量本地磁盘使用&#xff0c;亦可同时在跨平台、跨地区的不同主机上挂载读写。 JuiceFS 简介 JuiceFS…

推荐几款不错的AI绘画工具

随着近年来数据、算法等核心技术的不断进步&#xff0c;人工智能在内容创作各垂直领域的比例不断增加&#xff0c;包括人工智能写作、人工智能编辑和最近流行的人工智能绘画。 许多朋友也想跟上潮流&#xff0c;使用人工智能绘画生成软件创建人工智能图像&#xff0c;但我不知…

手机变局2023:一场瞄准产品和技术的“思维革命”

以折叠屏冲高端&#xff0c;已成为中国手机厂商们的共识。 在这个苹果未涉足的领域&#xff0c;国产手机厂商们加快脚步迭代推新&#xff0c;积极抢占机遇。但平心而论&#xff0c;虽然国产折叠屏机型众多&#xff0c;但市场上始终缺乏一款突破性的产品作为标杆&#xff0c;为…

数据结构【树】

第五章 树 一、树 1.定义&#xff1a;n个结点的集合&#xff0c;n0为空树&#xff1b;是递归的&#xff0c;是一种逻辑结构&#xff0c;同时也是一种分层结构&#xff1b; 特点 树的根结点没有前驱结点&#xff0c;除了根结点外的所有结点有且只有一个前驱结点&#xff1b;树…

Clion开发STM32之W5500系列(综合实验)

说明 此为w5500模块的综合实验测试模块,包含dhcp、dns、ntp以上三个模块的驱动参考之前的文章&#xff0c;本篇不做说明.使用的开发芯片 stm32f103vet6系列,外设接口使用的spi2 实验内容: 通过dhcp动态获取ip,通过dns解析NTP服务域名的ip通过NTP服务ip获取时间 w5500配置驱…

学生护眼台灯几瓦最舒适?2023全新五款护眼台灯推荐

每次经过学校&#xff0c;发现戴眼镜的小学生真的不少&#xff0c;通过近几年的儿童以及青少年的近视人数可看出&#xff0c;我国的近视人数中&#xff0c;儿童以及青少年占比53.5%&#xff0c;所以许多家长逐渐重视孩子用眼健康问题&#xff0c;会选择护眼台灯用于孩子写作业和…

第1章 获取数据库中的数据

CoreShop源程序是以数据库优先进行定义的&#xff0c;所以其本身不包含代码优先的定义&#xff0c;但本从更习惯于代码优先&#xff0c;所以为其定义了代码优先的定义。 1 CoreCms.Net.Model.Entities.SysRole using SqlSugar; using System.ComponentModel.DataAnnotations…

【JavaEE初阶】Tomcat安装与使用及初识Servlet

文章目录 1. Tomcat的安装与使用1.1 Tomcat安装1.2 Tomcat的启动1.3 Tomcat部署前端页面 2. Servlet2.1 Servlet是什么2.2 第一个Servlet程序2.3 常见错误 1. Tomcat的安装与使用 1.1 Tomcat安装 在浏览器中搜索Tomcat,打开官方网页.Tomcat官网 点击下载Tomcat8. 点击下载压…

PSP - 使用 MMseqs2 工具快速搜索蛋白质序列数据库 (GMGC)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131934642 MMseq2 是非常强大和高效的生物信息学软件&#xff0c;可以在极短的时间内对大规模的核苷酸和蛋白质序列进行搜索和聚类。主要特点有&a…

fpga_pwm呼吸灯(EP4CE6F17C8)

文章目录 一、呼吸灯二、代码实现三、引脚分配 一、呼吸灯 呼吸灯是指灯光在微电脑的控制之下完成由亮到暗的逐渐变化&#xff0c;使用开发板上的四个led灯实现1s间隔的呼吸灯。 二、代码实现 c module pwm_led( input clk ,input rst_n ,output reg [3:0] led ); …

c++网络编程:Boost.asio源码剖析

1、前言 Boost库是一个可移植、提供源代码的C库&#xff0c;作为标准库的后备&#xff0c;是C标准化进程的开发引擎之一。Boost库由C标准委员会库工作组成员发起&#xff0c;其中有些内容有望成为下一代C标准库内容。在C社区中影响甚大&#xff0c;是不折不扣的“准”标准库。…

未来行星探索希望:新型多脚机器人-团队版

机器人正在探索一个模拟的外星环境 即使一个机器人失败了&#xff0c;其余的团队成员也可以抵消它的损失。 背景 虽然探测器取得了令人难以置信的发现&#xff0c;但它们的轮子可能会拖慢它们的速度&#xff0c;而不稳定的地形可能会导致损坏。虽然没有东西可以取代“毅力号”…

Vue3输入框(Input)

APIs 参数说明类型默认值必传width输入框宽度string | number‘100%’falseaddonBefore设置前置标签string | slot‘’falseaddonAfter设置后置标签string | slot‘’falseallowClear可以点击清除图标删除内容booleanfalsefalsepassword是否启用密码框booleanfalsefalsedisabl…