【第九节】C++设计模式(结构型模式)-Composite(组合)模式

ops/2025/2/27 5:50:40/

目录

一、问题提出

二、模式结构 

三、代码实现 

三、总结 


一、问题提出

组合模式:构建树形结构的统一解决方案

        在软件开发中,我们经常需要处理树状的递归结构(例如文件系统、组织架构等)。这类场景中,组合模式(Composite Pattern)提供了一种优雅的解决方案,允许以统一的方式处理单个对象和对象组合,从而简化递归结构的构建和操作。

问题背景  
        当需要递归构建树状组合结构时,传统方法通常需要对“叶子节点”和“组合节点”进行区分处理,导致代码冗余和逻辑复杂。组合模式通过抽象公共接口,使得客户端可以无差别地操作单个对象和对象组合,有效解决了这一问题。

二、模式结构 

组合模式的典型结构包含以下核心角色:  
(1)抽象组件(Component)
           定义所有对象的公共接口,声明管理子节点的方法(如`Add`、`Remove`)。  
(2)叶子节点(Leaf)
           实现组件接口的末端对象,无子节点。  
(3)组合节点(Composite)
           实现组件接口,包含子节点集合,并通过递归调用管理子节点操作。

 

三、代码实现 

以下为组合模式的完整实现示例(C++语言):


代码片段 1:Component.h

// Component.h
#ifndef _COMPONENT_H_
#define _COMPONENT_H_/*** 抽象组件类(Component)* 定义所有节点(叶子节点和组合节点)的通用接口*/
class Component {
public:Component() = default;                     // 默认构造函数virtual ~Component() = default;           // 虚析构函数,确保正确释放派生类资源// 核心操作方法,子类必须实现virtual void Operation() = 0;// 子节点管理方法(默认空实现,叶子节点无需实现)virtual void Add(Component* com) {}        // 添加子节点virtual void Remove(Component* com) {}    // 移除子节点virtual Component* GetChild(int index) { return nullptr; } // 获取子节点
};#endif //~_COMPONENT_H_

代码片段 2:Component.cpp

// Component.cpp
#include "Component.h"// 默认构造函数
Component::Component() {// 初始化操作(如有需要)
}// 默认析构函数
Component::~Component() {// 资源清理操作(如有需要)
}// 添加子节点(默认空实现)
void Component::Add(Component* com) {// 叶子节点无需实现此方法
}// 移除子节点(默认空实现)
void Component::Remove(Component* com) {// 叶子节点无需实现此方法
}// 获取子节点(默认返回空指针)
Component* Component::GetChild(int index) {return nullptr; // 叶子节点无子节点
}


代码片段 3:Composite.h

// Composite.h
#ifndef _COMPOSITE_H_
#define _COMPOSITE_H_#include "Component.h"
#include <vector>/*** 组合节点类(Composite)* 包含子节点集合,并递归管理子节点操作*/
class Composite : public Component {
public:Composite() = default;                    // 默认构造函数~Composite();                             // 析构函数,释放子节点资源// 实现抽象组件接口void Operation() override;                // 递归执行子节点操作void Add(Component* com) override;        // 添加子节点void Remove(Component* com) override;     // 移除子节点Component* GetChild(int index) override;  // 获取指定索引的子节点private:std::vector<Component*> comVec;           // 子节点集合
};#endif //~_COMPOSITE_H_


代码片段 4:Composite.cpp

// Composite.cpp
#include "Composite.h"
#include <algorithm> // 用于std::find// 析构函数,释放所有子节点资源
Composite::~Composite() {for (auto& com : comVec) {delete com; // 递归删除子节点}
}// 递归执行所有子节点的操作
void Composite::Operation() {for (auto& com : comVec) {com->Operation(); // 委托子节点执行操作}
}// 添加子节点
void Composite::Add(Component* com) {comVec.push_back(com);
}// 移除子节点
void Composite::Remove(Component* com) {auto it = std::find(comVec.begin(), comVec.end(), com);if (it != comVec.end()) {comVec.erase(it); // 从集合中移除子节点}
}// 获取指定索引的子节点
Component* Composite::GetChild(int index) {if (index >= 0 && index < comVec.size()) {return comVec[index]; // 返回子节点指针}return nullptr; // 索引越界时返回空指针
}


代码片段 5:Leaf.h

// Leaf.h
#ifndef _LEAF_H_
#define _LEAF_H_#include "Component.h"/*** 叶子节点类(Leaf)* 实现组件接口,无子节点*/
class Leaf : public Component {
public:Leaf() = default;        // 默认构造函数~Leaf() = default;       // 默认析构函数void Operation() override; // 实现核心操作
};#endif //~_LEAF_H_


代码片段 6:Leaf.cpp

// Leaf.cpp
#include "Leaf.h"
#include <iostream>// 叶子节点的核心操作
void Leaf::Operation() {std::cout << "Leaf operation executed." << std::endl;
}


代码片段 7:main.cpp

// main.cpp
#include "Component.h"
#include "Composite.h"
#include "Leaf.h"
#include <iostream>int main() {// 创建叶子节点Leaf* leaf = new Leaf();leaf->Operation(); // 输出:Leaf operation executed.// 创建组合节点Composite* composite = new Composite();composite->Add(leaf); // 添加叶子节点到组合节点composite->Operation(); // 递归执行子节点操作// 获取并操作子节点Component* child = composite->GetChild(0);if (child) {child->Operation(); // 输出:Leaf operation executed.}// 释放资源delete composite; // 递归删除所有子节点return 0;
}

关键说明  
(1)子节点管理策略
           示例中使用`std::vector`存储子节点,实际可替换为链表、哈希表等其他数据结构。  
(2)默认空方法
        抽象组件中为`Add`、`Remove`等方法提供默认空实现,使叶子节点无需强制重写这些接口。

上述代码通过以下方式体现组合模式的核心思想:

(1)统一接口:`Component`类定义了叶子节点(`Leaf`)和组合节点(`Composite`)的通用接口(如`Operation`),使客户端可以无差别地操作两者。  
(2)叶子节点:`Leaf`实现`Operation`,表示树形结构的末端节点,无子节点。  
(3)组合节点:`Composite`维护子节点集合,递归调用子节点的`Operation`,支持动态添加和移除子节点。  
(4)递归操作:通过组合节点的递归调用,实现对树形结构的统一操作。 

模式对比  
与装饰器模式(Decorator)对比
        相似性:两者均通过组合方式扩展功能。  
        差异性: 装饰器模式旨在动态添加职责,不改变对象结构。  组合模式旨在统一处理树状结构,强调部分-整体的层次关系。  

三、总结 

        组合模式通过统一接口简化了树形结构的操作,尤其适用于需要递归处理对象的场景。其核心在于以一致的方式对待单个对象和组合对象,从而降低代码复杂度并提高扩展性。


http://www.ppmy.cn/ops/161599.html

相关文章

WPS接入私有化DeepSeek大语言模型

文章目录 1.安装officeAI软件1.1登录官网下载officeAI 2.officeAI相关配置2.1启动WPS第三方COM功能2.2接入本地ollama服务2.3演示示例 1.安装officeAI软件 OfficeAI 助手是一项专为 Microsoft Office 和 WPS 用户打造的智能办公工具软件&#xff0c;旨在解决多种常见办公问题。…

Deep seek学习日记1

Deepseek最强大的就是它的深度思考&#xff0c;并且展现了它的思考过程。 五种可使用Deep seek的方式&#xff08;应该不限于这五种&#xff0c;后续嵌入deepseek的应该更多&#xff0c;多了解一点因为官网容易崩~~&#xff09;&#xff1a; 1.deep seek官网 2.硅基流动silicon…

python的Tkinter小程序上传Excel并下载Text

实现一个图形化的Excel到文本文件转换工具&#xff0c;用户可以通过上传Excel文件并选择特定的列和行来生成一个文本文件。以下是详细的代码功能、使用的技术以及每一部分的详细注释&#xff1a; 1.功能概述 上传Excel文件&#xff1a;用户可以选择一个Excel文件进行上传。 选…

Linux相关概念和易错知识点(30)(线程互斥、线程同步)

目录 1.线程互斥 &#xff08;1&#xff09;临界资源和临界区 &#xff08;2&#xff09;互斥和原子性 ①互斥 ②原子性 &#xff08;3&#xff09;加锁和解锁&#xff08;互斥锁&#xff09;的原理 &#xff08;4&#xff09;pthread_mutex系列函数和变量 ①lock、unlo…

【自学笔记】Spring Boot框架技术基础知识点总览-持续更新

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Spring Boot框架技术基础知识点总览一、Spring Boot简介1.1 什么是Spring Boot&#xff1f;1.2 Spring Boot的主要特性 二、Spring Boot快速入门2.1 搭建Spring Boo…

Ajax数据采集与分析详解

文章目录 1. 什么是 Ajax&#xff1f;2. Ajax 的工作原理3. Ajax 在网页中的应用场景4. 爬取 Ajax 数据的方法4.1 分析网络请求4.2 模拟 Ajax 请求4.3 使用 Selenium 模拟浏览器4.4 使用 Headless 浏览器 5. 处理动态参数6. 处理分页和滚动加载7. 处理反爬虫机制8. 数据存储9. …

Linux 第三次脚本作业

源码编译安装httpd 2.4&#xff0c;提供系统服务管理脚本并测试&#xff08;建议两种方法实现&#xff09; 一、第一种方法 1、把 httpd-2.4.63.tar.gz 这个安装包上传到你的试验机上 2、 安装编译工具 (俺之前已经装好了&#xff09; 3、解压httpd包 4、解压后的httpd包的文…

【初阶数据结构】森林里的树影 “堆” 光:堆

文章目录 1.堆的概念及结构2.堆的接口实现2.1 堆的初始化2.2 堆的销毁2.3 堆的交换2.4 堆的向上调整2.5 堆的插入2.6 堆的向下调整2.7 堆的删除2.8 堆顶获取2.9 堆的判空2.10 堆的节点个数2.11 堆的打印2.12 堆的排序&#xff08;向上建堆&#xff09;2.13 堆的排序&#xff08…