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

news/2024/4/20 23:38:02/

目录

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.ppmy.cn/news/1035335.html

相关文章

通过css设置filter 属性,使整个页面呈现灰度效果,让整个网页变灰

通过css设置filter 属性设置页面整体置灰 效果图: 通过设置 filter 属性为 grayscale(100%)&#xff0c;页面中的所有元素都会被应用灰色滤镜效果&#xff0c;使整个页面呈现灰度效果。 <style type"text/css"> html { filter: grayscale(100%); -webkit-f…

智慧工地一体化云平台源码:监管端、工地端、危大工程、智慧大屏、物联网、塔机、吊钩、升降机

智慧工地解决方案依托计算机技术、物联网、云计算、大数据、人工智能、VR&AR等技术相结合&#xff0c;为工程项目管理提供先进技术手段&#xff0c;构建工地现场智能监控和控制体系&#xff0c;弥补传统方法在监管中的缺陷&#xff0c;最终实现项目对人、机、料、法、环的全…

MCA Recovery简介

概述 1、MCA Recovery – Execution Path 软件层辅助从不可纠正的数据错误恢复&#xff1b; 1&#xff09;处理器识别到硬件不可纠正错误&#xff0c;打上数据腐烂标签&#xff0c;事件交由固件或OS处理。 2&#xff09;如果固件/OS有冗余数据备份&#xff0c;可以被纠正&#…

C++ 基础知识 问答题(四)

Part1 1.深拷贝是什么&#xff1f;浅拷贝是什么&#xff1f; 2.new与malloc有什么区别&#xff1f; 3. 重载是什么&#xff1f;重定义&#xff08;隐藏&#xff09;是什么&#xff1f;重写是什么&#xff1f; 4.协变是什么&#xff1f; 5.const修饰成员函数的作用是什么&a…

thinkphp使用consul

service层 <?php namespace app\service;use http\Client; use think\facade\Config;class Consul {private $httpUrl;public $client;public function __construct(){$consulConfig Config::get(common.consul);$this->httpUrl $consulConfig[host].":".$c…

AIGC绘画:基于Stable Diffusion进行AI绘图

文章目录 AIGC深度学习模型绘画系统stable diffusion简介stable diffusion应用现状在线网站云端部署本地部署Stable Diffusion AIGC深度学习模型绘画系统 stable diffusion简介 Stable Diffusion是2022年发布的深度学习文本到图像生成模型&#xff0c;它主要用于根据文本的描述…

Spring中bean生命周期的PostProcessor的每个方法的作用

可结合这个博客看 https://blog.csdn.net/riemann_/article/details/118500805、https://cloud.tencent.com/developer/article/1409315、https://blog.csdn.net/qq_43631716/article/details/120239438 本篇内容借鉴于chatgtp,应该有错误&#xff0c;仅作方法应用的参考&#…

结构体指针变量的使用

1、结构体指针的引用 #include<iostream> using namespace std;struct Student {int num;char name[32]; }; int main() {struct Student stu {1,"张三"};struct Student* p &stu;system("pause"); return 0; } 2、通过结构体指针访问结构体…

stack+queue

适配器 介绍 在C的标准模板库&#xff08;STL&#xff09;中&#xff0c;有几种适配器&#xff0c;它们是一些容器或函数对象的包装&#xff0c;提供了不同的接口和功能&#xff0c;用于适应特定的需求 分类 STL中的适配器可以分为两类&#xff1a;容器适配器和迭代器适配器 容…

【实用插件】ArcGIS for AutoCAD插件分享下载

ArcGIS包含一系列功能&#xff0c;其中ArcGIS for AutoCAD一个免费的可下载的AutoCAD插件&#xff0c;它可简化将CAD和GIS数据整合在一起的过程提供互操作性。 ArcGIS for AutoCAD互操作性平台将连接AutoCAD和 ArcGIS&#xff0c;以增强使用地理环境设计CAD工程图时的用户体验…

数据库MySQL 创建查询恢复数据库

创建数据库 查询数据库 备份恢复数据库

PHP8的字符串操作2-PHP8知识详解

今日继续分享《php8的字符串操作》昨天一天都没有写多少&#xff0c;内容多&#xff0c;今天继续&#xff1a; 昨天分享的是1、使用trim()、rtrim()和ltrim()函数去除字符串首尾空格和特殊字符。2、使用strlen()函数和mb_strlen()函数获取字符串的长度。 3、截取字符串 PHP对…

Python源码05:使用Pyecharts画词云图图

**Pyecharts是一个用于生成 Echarts 图表的 Python 库。Echarts 是一个基于 JavaScript 的数据可视化库&#xff0c;提供了丰富的图表类型和交互功能。**通过 Pyecharts&#xff0c;你可以使用 Python 代码生成各种类型的 Echarts 图表&#xff0c;例如折线图、柱状图、饼图、散…

显卡nvidia-smi后 提示Faild 解决过程,包含卸载重装NVIDIA驱动步骤

显卡异常: 显卡nvidia-smi后 提示Faild 解决过程&#xff0c;卸载重装nvidia驱动步骤 文章目录 显卡异常: 显卡nvidia-smi后 提示Faild 解决过程&#xff0c;卸载重装nvidia驱动步骤 [toc]1 缘由2 解决过程3 过程所需命令4 解决4.1 把该显卡重新拔插一下卸载NVIDIA驱动的方法&a…

Github上git lfs oid sha256文件无法下载的解决方案

问题&#xff1a;github上sha文件无法下载&文件超出限制 当我克隆Github上的一个库时&#xff0c;其中有一个包的内容格式如下&#xff1a; version https://git-lfs.github.com/spec/v1 oid sha256:一堆数字和字母 size 一堆数字 这堆东西类似百度网盘的下载链接和密码&a…

Cpp学习——string模拟实现

目录 一&#xff0c;string的成员变量 二&#xff0c;string的各项功能函数 1.构造函数 2.析构函数 3.扩容函数 4.插入与删除数据的函数 5.运算符重载 6.打印显示函数 7&#xff0c;拷贝构造 8.find函数 一&#xff0c;string的成员变量 在模拟实现string之前&#xff…

前端代理配置

dev: {env: require(./dev.env),port: process.env.PORT || 8080,autoOpenBrowser: true,assetsSubDirectory: static,assetsPublicPath: /,proxyTable: {// 以 /party/fundamental/ 开头的请求&#xff0c;全部转发到 target 设置的地址/party/fundamental/: {// target: http…

原型模式 Prototype Pattern 《游戏编程模式》学习笔记

原型的定义 用原型实例指定创建对象的种类&#xff0c;并且通过拷贝这些原型创建新的对象。 举个例子 假设我现在要做一款游戏&#xff0c;这个游戏里有许多不同种类的怪物&#xff0c;鬼魂&#xff0c;恶魔和巫师。这些怪物通过“生产者”进入这片区域&#xff0c;每种敌人…

linux系统部署jenkins详细教程

一、Linux环境 1、下载war包 官网下载地址&#xff1a; https://get.jenkins.io/war-stable/2.332.4/jenkins.war 2、将war包上传至服务器 创建目录/home/ubuntu/jenkins 上传war包至该目录 3、将jenkins添加到环境变量 进入环境变量文件 vim /etc/profile # 文件下方追加…

学习笔记十四:K8S最小调度单元POD概述

K8S最小调度单元POD概述 k8s核心资源Pod介绍Pod是什么Pod如何管理多个容器Pod网络Pod存储代码自动发版更新收集业务日志 Pod工作方式自主式Pod控制器管理的Pod(防误删除) 如何基于Pod运行应用 k8s核心资源Pod介绍 K8s官方文档&#xff1a;https://kubernetes.io/ K8s中文官方文…