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

发布于:2025-02-27 ⋅ 阅读:(9) ⋅ 点赞:(0)

目录

一、问题提出

二、模式结构 

三、代码实现 

三、总结 


一、问题提出

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

        在软件开发中,我们经常需要处理树状的递归结构(例如文件系统、组织架构等)。这类场景中,组合模式(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)对比
        相似性:两者均通过组合方式扩展功能。  
        差异性: 装饰器模式旨在动态添加职责,不改变对象结构。  组合模式旨在统一处理树状结构,强调部分-整体的层次关系。  

三、总结 

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