(二)结构型模式: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.mfbz.cn/a/82320.html

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

相关文章

【C语言学习】二维数组

二维数组 int[3][5];//通常理解为a是一个3行5列的矩阵二维数组的遍历 for(i0; i<3; i){for(j0; j<5; j){a[i][j] i*j;} }

Vivado使用入门之三:I/O约束

一、导图概览 二、I/O约束 2.1 I/O约束的内容 I/O约束主要是对port的位置和电气特性进行设置&#xff0c;进入菜单栏Window的IO Ports&#xff0c;可以查看可约束的相关内容。 一些port的常用特性解释如下 Name: port的名称 Direction:port的输入输出类型&#xff0c;有三种…

DNNGP、DeepGS 和 DLGWAS模型构成对比

一、DNNGP DNNGP 是基于深度卷积神经网络&#xff0c;这个结构包括一个输入层&#xff0c;三个卷积层&#xff0c;一个批标准化层&#xff0c;两个dropout层&#xff0c;一个平坦化层&#xff0c;一个 dense层。 dropout层&#xff1a;在神经网络中,dropout层是一个非常有效的正…

[JavaWeb]【一】入门JavaWeb开发总概及HTML、CSS、JavaScript

目录 一 特色 二 收获​编辑 三 什么是web? 四 网站的工作流程 五 web网站的开发模式​编辑 六 web开发课程学习安排 七、初始web前端 八 HTML、CSS 8.1 什么是HTNL\CSS(w3cschool) 8.2 HTML快速入门 8.3 VS Code开发工具 8.3.1 插件 8.3.2 主题&#xff08;改变颜色&…

破解难题:如何应对项目中的‘老油条’障碍

引言 在项目管理的实践中&#xff0c;我们经常遇到各种各样的人员挑战。其中&#xff0c;有一种特殊的挑战被称为“老油条”现象。这些“老油条”通常在表面上表现得非常配合&#xff0c;但在实际工作中却常常没有任何进展。这种情况不仅会影响项目的进度&#xff0c;还可能对…

Kestrel和ISS服务器下的配置

一、Kestrel服务器 Kestrel是ASP.NET Core框架中的一个跨平台的Web服务器。它是ASP.NET Core应用程序默认的HTTP服务器&#xff0c;并且可作为独立的Web服务器来托管ASP.NET Core应用程序。 Kestrel具有以下特点和功能 1、跨平台 Kestrel是完全跨平台的&#xff0c;可以在Wind…

Git如何上传文件到github

Git下载网址&#xff1a; https://git-scm.com/downloads 1. 新建一个空文件夹&#xff0c;用来上传文件&#xff0c;第一次需创建&#xff0c;以后无需创建 2. 点进去空文件夹&#xff0c;鼠标右键&#xff0c;使用Git Bash Here 打开 3. 克隆远程仓库&#xff1a;git cl…

nginx反向代理、负载均衡

修改nginx.conf的配置 upstream nginx_boot{# 30s内检查心跳发送两次包&#xff0c;未回复就代表该机器宕机&#xff0c;请求分发权重比为1:2server 192.168.87.143 weight100 max_fails2 fail_timeout30s; server 192.168.87.1 weight200 max_fails2 fail_timeout30s;# 这里的…

WPF显示初始界面--SplashScreen

WPF显示初始界面–SplashScreen 前言 WPF应用程序的运行速度快&#xff0c;但并不能在瞬间启动。当第一次启动应用程序时&#xff0c;会有一些延迟&#xff0c;因为公共语言运行时&#xff08;CLR&#xff09;首先需要初始化.NET环境&#xff0c;然后启动应用程序。 对于WPF中…

OpenAI Function calling

开篇 原文出处 最近 OpenAI 在 6 月 13 号发布了新 feature&#xff0c;主要针对模型进行了优化&#xff0c;提供了 function calling 的功能&#xff0c;该 feature 对于很多集成 OpenAI 的应用来说绝对是一个“神器”。 Prompt 的演进 如果初看 OpenAI 官网对function ca…

【LeetCode-中等题】49. 字母异位词分组

题目 题解一:排序哈希表 思路:由于互为字母异位词的两个字符串包含的字母相同&#xff0c;因此对两个字符串分别进行排序之后得到的字符串一定是相同的&#xff0c;故可以将排序之后的字符串作为哈希表的键。 核心api: //将字符串转换为字符数组char[] ch str.toCharArray();…

使用open cv进行角度测量

使用open cv进行角度测量 用了一点初中数学的知识&#xff0c;准确度&#xff0c;跟鼠标点的准不准有关系&#xff0c;话不多说直接上代码 import cv2 import mathpath "test.jpg" img cv2.imread(path) pointsList []def mousePoint(event, x, y, flags, param…

【Linux取经路】解析环境变量,提升系统控制力

文章目录 一、进程优先级1.1 什么是优先级&#xff1f;1.2 为什么会有优先级&#xff1f;1.3 小结 二、Linux系统中的优先级2.1 查看进程优先级2.2 PRI and NI2.3 修改进程优先级2.4 进程优先级的实现原理2.5 一些名词解释 三、环境变量3.1 基本概念3.2 PATH&#xff1a;Linux系…

开源后台管理系统Geekplus Admin

本系统采用前后端分离开发模式&#xff0c;后端采用springboot开发技术栈&#xff0c;mybatis持久层框架&#xff0c;redis缓存&#xff0c;shiro认证授权框架&#xff0c;freemarker模版在线生成代码&#xff0c;websocket消息推送等&#xff0c;后台管理包含用户管理&#xf…

8. 实现业务功能--用户注册

目录 1. 顺序图 2. 参数要求 3. 接口规范 4. 创建扩展 Mapper.xml 5. 修改 DAO 6. 创建 Service 接口 7. 实现接口 8. 测试接口 9. 实现 Controller 9.1 密码加密处理 10. 实现前端界面 业务实现过程中主要的包和目录及主要功能&#xff1a; model 包&#xff1a;实体对象 d…

蛊卦-拨乱反正

目录 前言 卦辞 爻辞 总结 前言 题外话&#xff0c;今天占卜时&#xff0c;看错了&#xff0c;以为占到了蛊卦&#xff08;后续会对自己的占卦经历进行补充&#xff0c;不断完善这个易经学习的专栏&#xff09;&#xff0c;那顺便就学习一下蛊卦&#xff0c;蛊惑人心&#…

QT TLS initialization failed问题(已解决) QT基础入门【网络编程】openssl

问题: qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed 这个问题的出现主要是使用了https请求:HTTPS ≈ HTTP + SSL,即有了加密层的HTTP 所以Qt 组件库需要OpenSSL dll 文件支持HTTPS 解决: 1.加入以下两行代码获取QT是否支持opensll以…

STM32--TIM定时器(3)

文章目录 输入捕获简介频率测量输入捕获通道输入捕获基本结构PWMI的基本结构输入捕获模式测量PWM频率和占空比代码 编码器接口正交编码器工作模式接口基本结构TIM编码接口器测速代码&#xff1a; 输入捕获简介 输入捕获IC(Input Capture)&#xff0c;是处理器捕获外部输入信号…

JVM——引言+JVM内存结构

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

mybatis plus 配置自动设置创建时间和创建人id

1.新建 MyMetaObjectHandler package com.ruoyi.framework.config;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import com.ruoyi.common.bean.LocalUser; import com.ruoyi.coupon.domain.CouponUser; import org.apache.ibatis.reflection.MetaObjec…
最新文章