组合模式(Composite Pattern)

定义

组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构,并且能像使用单独对象一样使用组合对象。组合模式让客户端代码对单个对象和复合对象的使用具有一致性。

在组合模式中,我们定义以下几个角色:

  1. Component:这是一个抽象组件接口,它定义了所有组件共有的行为。这些行为包括添加和删除子组件、显示子组件等。

  2. Leaf:这是具体组件,也就是叶子节点,它实现了组件接口,但没有子组件。

  3. Composite:这也是具体组件,但它充当容器角色,它持有一组子组件,并实现了组件接口。Composite 负责在其内部实现子组件的递归组合。

示例

下面是一个C++中使用组合模式的示例,我们创建一个简单的图形系统,其中包含圆形、矩形和组合图形(可以包含其他图形):

#include <iostream>  
#include <vector>  // 组件接口  
class Shape {  
public:  virtual void draw() = 0;  virtual void add(Shape* shape) = 0;  virtual void remove(Shape* shape) = 0;  virtual std::vector<Shape*> getChildren() = 0;  
};  // 叶子节点:圆形  
class Circle : public Shape {  
private:  int radius;  public:  Circle(int radius) : radius(radius) {}  void draw() override {  std::cout << "Drawing Circle with radius: " << radius << std::endl;  }  void add(Shape* shape) override {  // 圆形不能添加子组件  }  void remove(Shape* shape) override {  // 圆形不能删除子组件  }  std::vector<Shape*> getChildren() override {  return {}; // 圆形没有子组件  }  
};  // 叶子节点:矩形  
class Rectangle : public Shape {  
private:  int width, height;  public:  Rectangle(int width, int height) : width(width), height(height) {}  void draw() override {  std::cout << "Drawing Rectangle with width: " << width << " and height: " << height << std::endl;  }  void add(Shape* shape) override {  // 矩形不能添加子组件  }  void remove(Shape* shape) override {  // 矩形不能删除子组件  }  std::vector<Shape*> getChildren() override {  return {}; // 矩形没有子组件  }  
};  // 容器节点:组合图形  
class CompositeShape : public Shape {  
private:  std::vector<Shape*> children;  public:  void draw() override {  std::cout << "Drawing CompositeShape:" << std::endl;  for (Shape* child : children) {  child->draw();  }  }  void add(Shape* shape) override {  children.push_back(shape);  }  void remove(Shape* shape) override {  auto it = std::find(children.begin(), children.end(), shape);  if (it != children.end()) {  children.erase(it);  }  }  std::vector<Shape*> getChildren() override {  return children;  }  
};  int main() {  // 创建组合图形  CompositeShape composite;  // 添加子组件  composite.add(new Circle(5));  composite.add(new Rectangle(10, 20));  // 创建另一个组合图形,并添加到之前的组合图形中  CompositeShape anotherComposite;  anotherComposite.add(new Circle(10));  anotherComposite.add(new Rectangle(5, 15));  composite.add(&anotherComposite); // 注意这里传递的是指针  // 绘制组合图形  composite.draw();  // 清理资源(在实际应用中,你可能需要更复杂的内存管理策略)  for (Shape* child : composite.getChildren()) {  delete child;  }  return 0;  
}

在这个示例中,Shape 是一个抽象组件接口,它定义了所有组件共有的行为。Circle 和 Rectangle 是具体组件(叶子节点),它们实现了 Shape 接口但没有子组件。CompositeShape 是容器组件,它持有一组子组件,并实现了 Shape 接口。

在组合模式示例中,CompositeShape 类扮演着组合对象的角色,它管理着一组子组件,并提供了添加、删除和绘制子组件的方法。由于 CompositeShape 也实现了 Shape 接口,它可以在其他组合对象中被当作一个普通的组件来使用,从而实现了对象组合的一致性。

组合模式的主要优点有:

  1. 一致性:客户端代码可以以一致的方式来处理单个对象和组合对象,无需关心对象是否是复合的。

  2. 扩展性:你可以方便地添加新的组件类型,因为系统是基于接口而不是具体类构建的。

  3. 灵活性:你可以很容易地组合和分解对象,因为组件之间的层次结构是动态的。

  4. 封装性:组合模式允许你将一些对象组合成一个树形结构来表现“部分-整体”的层次结构,并且能像使用单个对象一样使用组合对象。

然而,组合模式也有一些潜在的缺点:

  1. 复杂性:组合模式可能会增加系统的复杂性,特别是当组合对象嵌套层次很深时。

  2. 内存使用:如果组合对象包含大量子组件,可能会占用较多的内存。

  3. 性能开销:在遍历组合对象以执行某些操作时,可能会产生额外的性能开销。

在实际应用中,组合模式常用于实现如文件/目录结构、UI组件树、编译器中的语法树等场景,其中整体和部分可以以同样的方式被对待。

回到示例代码,在 main 函数中,我们创建了一个 CompositeShape 对象 composite,并向其添加了几个子组件,包括 Circle 和 Rectangle 对象,以及另一个 CompositeShape 对象 anotherComposite。然后我们调用 draw 方法来绘制整个组合对象。在绘制过程中,CompositeShape 会递归地调用其所有子组件的 draw 方法,从而实现了组合对象的绘制。

最后,我们需要注意资源管理问题。在这个示例中,我们手动删除了所有动态分配的对象,以避免内存泄漏。在实际应用中,你可能需要采取更复杂的内存管理策略,例如使用智能指针(如 std::shared_ptr 或 std::unique_ptr)来自动管理对象的生命周期。

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

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

相关文章

Spring Boo项目中方法参数对象中字段上存在的自定义注解如何进行拦截解析

一、前言 在Spring Boot项目开发过程中&#xff0c;我们经常会使用到自定义注解的方式进行业务逻辑开发&#xff0c;此时注解我们一般是放在方法或者类上面&#xff0c;通过AOP切面拦截的方式进行自定义业务逻辑填充。但是如果自定义注解放在类的字段上&#xff0c;此时应该如…

Clickhouse填坑记4:Too many parts问题分析

Clickhouse在进行大数据量同步时,感觉很爽,插入速度非常快,但是,在使用过程中却出现了几次“Too many parts”异常报错,搞得很痛苦,这里记录一下解决过程。 我这边采用的是Flink程序,实时将数据写入ClickHouse,在执行一段时间后,会提示“Too many parts”异常,如下异…

云端技术驾驭DAY13——Pod污点、容忍策略、Pod优先级与抢占、容器安全

往期回顾&#xff1a; 云端技术驾驭DAY01——云计算底层技术奥秘、云服务器磁盘技术、虚拟化管理、公有云概述 云端技术驾驭DAY02——华为云管理、云主机管理、跳板机配置、制作私有镜像模板 云端技术驾驭DAY03——云主机网站部署、web集群部署、Elasticsearch安装 云端技术驾驭…

XXE 漏洞简单研究

近期在做个基础的 web 常见漏洞的 ppt&#xff0c;主要参考 OWASP TOP 10 2017RC2&#xff0c;此版本中增加了 XXE 攻击&#xff0c;所以自己简单的研究下 XXE 攻击。XXE&#xff08;XML External Entity&#xff09;XML 外部实体&#xff0c;当前端和后端通信数据采用 xml&…

element el-date-picker 日期组件置灰指定日期范围、禁止日期范围日期选择

JS如何将当前日期或指定日期转时间戳_javascript技巧_脚本之家 小于指定日期前的日期置灰 比如这里 指定日期是 2024-02-20 10:48:15 disabledDate(time) time是一个函数提供的时间用于比较 他是一个时间戳↓ 理解为我们想要置灰的时间 time.getTime() < timeStamps- 1 *…

《Large Language Models for Generative Information Extraction: A Survey》阅读笔录

论文地址&#xff1a;Large Language Models for Generative Information Extraction: A Survey 前言 映像中&#xff0c;比较早地使用“大模型“”进行信息抽取的一篇论文是2022年发表的《Unified Structure Generation for Universal Information Extraction》&#xff0c;也…

IDEA开发环境热部署

开发环境热部署 在实际的项目开发调试过程中会频繁地修改后台类文件&#xff0c;导致需要重新编译重新启动&#xff0c;整个过程非常麻烦&#xff0c;影响开发效率。Spring Boot提供了spring-boot-devtools组件&#xff0c;使得无须手动重启SpringBoot应用即可重新编译、启动项…

cesium相机视角跳转和缩放至entity方法汇总

下面汇总的相机视角跳转方法有很多种&#xff0c;都是根据某一个经纬度高程坐标[x,y,z]&#xff0c;Entity实体或者矩形四至范围[west , south , east , north]作为视图跳转到目标范围的中心&#xff0c;然后在该位置上设置相机相对的偏移量&#xff0c;这个偏移量主要是设置相…

36.云原生之SpringCloud+k8s实践

云原生专栏大纲 文章目录 SpringCloudk8s介绍spring-cloud-kubernetes服务发现配置管理负载均衡选主 spring-cloud-bookinfo案例构建项目环境配置namespace部署与验证productpagegatewaybookinfo-admindetailsratingsreviewsreviews-v1reviews-v2 总结 SpringCloudk8s介绍 ht…

vue-router4 (六) 路由嵌套

应用场景&#xff1a; ①比如京东页面的首页、购物车、我的按钮&#xff0c;可以点击切换到对应的页面&#xff1b; ② 比如 Ant Design左侧这些按钮点击就会切到对应的页面&#xff0c;此时可以把左侧按钮放在父路由中&#xff0c;右侧的子路由 1.路由配置&#xff0c;子路由…

将法律条文很美观的复制到word上

前言 目前很多法律条款都没有现成的PDF或者word格式的供大家下载&#xff0c;这个时候呢&#xff0c;领导又要求你帮他搞定&#xff0c;这就很。。。。 步骤 复制全部条款到word中使用wps的排版功能&#xff0c;将空格和空段落全部移除 3. 设置好你需要的格式 标题&#xff…

常用对象的遍历方法

var obj [{name: 1111,account: {01: { name: 1.1 },02: { name: 1.2 },03: { name: 1.3 },04: { name: 1.4 },05: { name: 1.5 },}} ]var nowObj obj[0].account;1、for…in 任意顺序遍历对象所有的可枚举属性&#xff08;包括对象自身的和继承的可枚举属性&#xff0c;不含…

影像仪激光扫描功能,无缝连接2D/3D混合测量

在现代工业生产领域&#xff0c;影像仪用于质量控制和产品检测&#xff0c;是一个不可或缺的工具。它通过高精度的成像和图像处理技术&#xff0c;可以及时发现产品的缺陷和异常&#xff0c;以保证产品质量的稳定性和一致性。 影像仪的重要性及其面临的挑战 在工业生产方面&a…

视频生成模型(猜测sora)demo

import numpy as np import paddle import paddle.nn as nn import paddle.nn.functional as Fclass FeedForward(nn.Layer):def __init__(self, hidden_dim)

代码随想录算法训练营第42天|● 1049. 最后一块石头的重量 II ● 494. 目标和 ● 474.一和零

文章目录 1049.最后一块石头的重量II思路&#xff1a;动归五部曲代码&#xff1a; ● 494. 目标和思路五部曲1.确定dp数组五部曲2.确定dp公式3.dp初始化4.遍历顺序 代码&#xff1a; ● 474.一和零思路动归五部曲 代码&#xff1a; 1049.最后一块石头的重量II 思路&#xff1a;…

go test用法(获取单元测试覆盖率)

go test用法&#xff08;获取ut覆盖率&#xff09; 为了提升系统的稳定性&#xff0c;一般公司都会对代码的单元测试覆盖率有一定要求。下面针对golang自带的测试命令go test做讲解。 1 命令 1.1 go test ./… &#xff08;运行当前目录及所有子目录下的测试用例&#xff09; …

ubuntu——解决复制粘贴问题

执行以下四步&#xff1a; ①更新源 sudo apt update ②使用APT&#xff08;高级包管理工具&#xff09;来自动移除系统中未使用的依赖包&#xff0c;并且将open-vm-tools软件包及其相关的未使用的依赖包一并移除。 sudo apt-get autoremove open-vm-tools 注&#xff1a;…

【virtual Box】功能速通:安装 Windows 和 Ubuntu

文章目录 一、虚拟机1.1 概述1.2 virtual box概述 二、新建虚拟机、删除、注册三、虚拟机内部设置3.1 安装增强功能驱动3.2 分辨率问题3.3 网络链接方式 一、虚拟机 1.1 概述 虚拟机&#xff08;Virtual Machine&#xff0c;VM&#xff09;是一种软件实现的计算机系统&#x…

【Nginx笔记02】通过Nginx服务器转发客户端的WebSocket接口到后端服务

这篇文章&#xff0c;主要介绍如何通过Nginx服务器转发客户端的WebSocket接口到后端服务【知识星球】。 目录 一、Nginx配置WebSocket 1.1、Nginx配置内容 1.2、客户端请求地址 1.3、创建WebSocket测试工程 1.4、启动测试 1.5、WebSocket超时问题 1.5.1、设置超时时间 …

纪念创作百日——感悟与展望

时光荏苒&#xff0c;仿佛眨眼之间&#xff0c;我已在CSDN这个充满智慧与激情的平台上创作了七十多篇文章。回首这段百日创作之旅&#xff0c;我不禁感慨万千&#xff0c;同时也更加深刻地体会到了写作的魅力所在。 在这个数字化、信息化的时代&#xff0c;写作成为了一种独特…