(二)结构型模式:4、组合模式(Composite Pattern)(C++实例)

目录

1、组合模式(Composite Pattern)含义

2、组合模式应用场景

3、组合模式的优缺点

4、组合模式的UML图学习

5、C++实现组合模式的简单示例(公司的OA系统)


1、组合模式(Composite Pattern)含义

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.
将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。 (来自《设计模式之禅》)

2、组合模式应用场景

(1)当你发现需求中是体现部分与整体层次的结构时,例如文件系统,视图树,公司组织架构等;

(2)当你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就可以考虑组合模式;

3、组合模式的优缺点

(1)优点:

1)简化客户端代码:组合模式使得客户端可以统一对待单个对象和组合对象,无需区分它们的类型,从而简化了客户端的代码。

2)灵活性和可扩展性:通过组合模式,可以动态地添加、删除和修改对象的结构,使得系统更加灵活,并且易于扩展。

3)统一操作接口:组合模式定义了统一的操作接口,使得客户端可以一致地处理单个对象和组合对象,无需关心具体对象的类型。

4)便于创建复杂对象结构:组合模式可以将对象组织成树形结构,从而方便地创建和管理复杂的对象结构。

(2)缺点:

1)设计复杂性增加:使用组合模式会引入更多的类和对象,从而增加了系统的设计复杂性。这可能会导致代码结构变得复杂,不易理解和维护。

2)不适合所有场景:组合模式适用于表示整体-部分层次结构的情况,但并不是所有情况都适合使用组合模式。如果对象之间没有明显的层次关系或者不需要统一对待单个对象和组合对象,那么使用组合模式可能会带来不必要的复杂性。

3)难以限制组件类型:在组合模式中,组合对象可以包含其他组合对象或叶子对象。这意味着在编译时很难强制限制组件的类型,可能会导致一些运行时错误。

4)可能造成性能损失:由于组合模式涉及到递归遍历整个对象树,可能会导致性能上的一些损失。特别是当对象树非常庞大时,遍历操作可能会消耗较多的时间和资源。

尽管组合模式存在一些缺点,但它仍然是一种强大且常用的设计模式,特别适用于需要处理层次结构的场景。在使用组合模式时,需要根据具体的需求和系统设计来权衡其优缺点,并确保合理地应用该模式。

4、组合模式的UML图学习

组成元素:

(1)抽象构件角色(Composite):是组合中对象声明接口,实现所有类共有接口的默认行为。

(2)树叶构件角色(Leaf):上述提到的单个对象,叶节点没有子节点。

(3)树枝构件角色(Composite):定义有子部件的组合部件行为,存储子部件,在Component接口中实现与子部件有关的操作。

(4)客户端(Client):使用 Component 部件的对象。

5、C++实现组合模式的简单示例(公司的OA系统)

#include <iostream>
#include <string>
#include <vector>// 组件接口
class Component 
{
public:virtual void display() const = 0;
};// 叶子对象:员工
class Employee : public Component 
{
private:std::string name;public:Employee(const std::string& name) : name(name) {}void display() const override {std::cout << "Employee: " << name << std::endl;}
};// 组合对象:部门
class Department : public Component 
{
private:std::string name;std::vector<Component*> members;public:Department(const std::string& name) : name(name) {}void add(Component* member) {members.push_back(member);}void remove(Component* member) {// 在实际应用中可能需要更复杂的逻辑来删除成员members.erase(std::remove(members.begin(), members.end(), member), members.end());}void display() const override {std::cout << "Department: " << name << std::endl;for (const auto& member : members) {member->display();}}
};int main() 
{// 创建公司的组织结构Department company("Company");Department department1("Department 1");Employee employee1("Employee 1");Employee employee2("Employee 2");Department department2("Department 2");Employee employee3("Employee 3");Employee employee4("Employee 4");// 构建组织结构company.add(&department1);company.add(&department2);department1.add(&employee1);department1.add(&employee2);department2.add(&employee3);department2.add(&employee4);// 显示公司的组织结构company.display();return 0;
}

在上述示例中,我们创建了一个 Component 接口作为组件的基类,其中包含了一个 display 方法。Employee 类表示叶子对象,Department 类表示组合对象。Department 类中使用了一个 vector 来存储成员。

在 main 函数中,我们创建了一个公司对象 company 和两个部门对象 department1 和 department2,以及四个员工对象 employee1、employee2、employee3 和 employee4。然后,将部门和员工添加到公司的组织结构中。最后,调用 company 的 display 方法,会递归地显示整个公司的组织结构。

运行以上代码,输出将会是:

Department: Company

Department: Department 1

Employee: Employee 1

Employee: Employee 2

Department: Department 2

Employee: Employee 3

Employee: Employee 4

可以看到,组合对象的 display 方法成功地递归调用了所有子组件的 display 方法,从而展示了公司的组织结构。

通过组合模式,我们可以以统一的方式管理和操作公司的组织结构,从而简化了代码的使用和维护。

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

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

相关文章

207. 课程表

思路 首先要完全理解题意&#xff0c;这道题的[a,b]并不是b满足了a就可以真正的学习a这门课了&#xff0c;因为a还有可能需要其他选修课的条件。类似下图。   这题的思路在于使用合适的数据结构来存储&#xff0c;这里用hash表来存储如果1这门课可以修了之后&#xff0c;可以…

ElasticSearch 数据聚合、自动补全(自定义分词器)、数据同步

文章目录 数据聚合一、聚合的种类二、DSL实现聚合1、Bucket&#xff08;桶&#xff09;聚合2、Metrics&#xff08;度量&#xff09;聚合 三、RestAPI实现聚合 自动补全一、拼音分词器二、自定义分词器三、自动补全查询四、实现搜索款自动补全&#xff08;例酒店信息&#xff0…

AI问答:JSBridge / WebView 与 Native 通信

一、理解JSBridge JSBridge是一种连接JavaScript和Native代码的桥梁&#xff0c;它提供了一种方法&#xff0c;使得JavaScript可以直接调用Native的代码&#xff0c;同时使得Native的代码也能直接调用JavaScript的方法&#xff0c;从而实现了JavaScript和Native之间的相互调用和…

uniapp配置添加阿里巴巴图标icon流程步骤

文章目录 下载复制文件到项目文件夹里项目配置目录结构显示图标 下载 阿里巴巴icon官网 https://www.iconfont.cn/ 复制文件到项目文件夹里 项目配置目录结构 显示图标

【【STM32之GPIO】】

STM32之GPIO 学完了正点原子自带的视频课之后感觉仍然一知半解现在更新一下来自其他版本的STM32学习 GPIO 就是 General Purpose Input Output 中文名叫通用输入输出口 可配置8种输入输出模式 引脚电平 0V~3.3V 部分引脚可容忍5V 输出模式下可控制端口输出高低电平&#xff…

【C++ 记忆站】命名空间

文章目录 命名空间概念命名空间的定义1、正常的命名空间定义2、命名空间可以嵌套3、同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中 命名空间的使用1、加命名空间名称及作用域限定符2、使用using将命名空间中某个成员引入3、使用using namespac…

Vue初识别--环境搭建--前置配置过程

问题一&#xff1a; 在浏览器上的扩展程序上添加了vue-devtools后不生效&#xff1a; 解决方式&#xff1a;打开刚加入的扩展工具Vue.js devtools的允许访问文件地址设置 问题二&#xff1a;Vue新建一个项目 创建一个空文件夹hrsone&#xff0c;然后在VSCode中打开这个空文件夹…

el-table实现懒加载(el-table-infinite-scroll)

2023.8.15今天我学习了用el-table对大量的数据进行懒加载。 效果如下&#xff1a; 1.首先安装&#xff1a; npm install --save el-table-infinite-scroll2 2.全局引入&#xff1a; import ElTableInfiniteScroll from "el-table-infinite-scroll";// 懒加载 V…

CentOS系统环境搭建(九)——centos系统下使用docker部署项目

centos系统环境搭建专栏&#x1f517;点击跳转 关于Docker-compose安装请看CentOS系统环境搭建&#xff08;三&#xff09;——Centos7安装Docker&Docker Compose&#xff0c;该文章同样收录于centos系统环境搭建专栏。 Centos7部署项目 采用前后端分离的形式部署。使用Do…

JVM——引言+JVM内存结构

引言 什么是JVM 定义: Java VirtualMachine -java 程序的运行环境 (ava 二进制字节码的运行环境) 好处: 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收功能数组下标越界检查&#xff0c;多态 比较: jvm jre jdk 学习jvm的作用 面试理解底层实现原理中…

【Freertos基础入门】队列(queue)的使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、队列是什么&#xff1f;二、队列的操作二、示例代码总结 前言 本系列基于stm32系列单片机来使用freerots FreeRTOS是一个广泛使用的开源实时操作系统&…

CVE-2015-5254漏洞复现

1.漏洞介绍。 Apache ActiveMQ 是美国阿帕奇&#xff08;Apache&#xff09;软件基金会所研发的一套开源的消息中间件&#xff0c;它支持 Java 消息服务&#xff0c;集群&#xff0c;Spring Framework 等。Apache ActiveMQ 5.13.0之前 5.x 版本中存在安全漏洞&#xff0c;该漏…