当前位置: 首页 > news >正文

组合模式(Composite Pattern)及其应用场景

组合模式是一种结构型设计模式,它允许你将对象组合成树形结构来表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

模式定义

组合模式通过将对象组合成树状结构来表示部分-整体的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

模式结构

  • Component(抽象构件): 定义叶子和容器构件的共同接口

  • Leaf(叶子构件): 表示叶节点对象,没有子节点

  • Composite(容器构件): 表示容器节点对象,存储子部件并实现与子部件相关的操作

  • Client(客户端): 通过Component接口操作组合结构中的对象

应用场景

  1. 需要表示对象的"部分-整体"层次结构时

  2. 希望用户忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时

  3. 处理树形结构数据时

  4. 当系统需要动态地在层次结构中添加新的构件时

优点

  1. 可以清楚地定义分层次的复杂对象

  2. 客户端可以一致地使用组合结构和单个对象

  3. 更容易在组合体内加入新的构件

  4. 简化了客户端代码,客户端可以一致地处理简单元素和复杂元素

缺点

  1. 设计较复杂,客户端需要花更多时间理清类之间的层次关系

  2. 很难限制组合中的构件类型

  3. 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则

C++实用示例

示例1:文件系统实现

#include <iostream>
#include <string>
#include <vector>
#include <memory>// 抽象构件
class FileSystemComponent {
public:virtual ~FileSystemComponent() = default;virtual void display(int depth = 0) const = 0;virtual void add(std::unique_ptr<FileSystemComponent> component) {throw std::runtime_error("Cannot add to a leaf component");}
};// 叶子构件 - 文件
class File : public FileSystemComponent {std::string name;
public:explicit File(const std::string& name) : name(name) {}void display(int depth = 0) const override {std::cout << std::string(depth * 2, ' ') << "- " << name << std::endl;}
};// 容器构件 - 目录
class Directory : public FileSystemComponent {std::string name;std::vector<std::unique_ptr<FileSystemComponent>> children;
public:explicit Directory(const std::string& name) : name(name) {}void display(int depth = 0) const override {std::cout << std::string(depth * 2, ' ') << "+ " << name << std::endl;for (const auto& child : children) {child->display(depth + 1);}}void add(std::unique_ptr<FileSystemComponent> component) override {children.push_back(std::move(component));}
};int main() {auto root = std::make_unique<Directory>("Root");auto documents = std::make_unique<Directory>("Documents");documents->add(std::make_unique<File>("Resume.pdf"));documents->add(std::make_unique<File>("CoverLetter.docx"));auto pictures = std::make_unique<Directory>("Pictures");pictures->add(std::make_unique<File>("Vacation.jpg"));pictures->add(std::make_unique<File>("Family.png"));auto downloads = std::make_unique<Directory>("Downloads");downloads->add(std::make_unique<File>("Setup.exe"));root->add(std::move(documents));root->add(std::move(pictures));root->add(std::make_unique<File>("README.txt"));root->add(std::move(downloads));root->display();
}

示例2:图形绘制系统

#include <iostream>
#include <vector>
#include <memory>
#include <cmath>// 抽象构件
class Graphic {
public:virtual ~Graphic() = default;virtual void move(int x, int y) = 0;virtual void draw() const = 0;
};// 叶子构件 - 点
class Dot : public Graphic {int x, y;
public:Dot(int x, int y) : x(x), y(y) {}void move(int x, int y) override {this->x += x;this->y += y;}void draw() const override {std::cout << "Drawing a dot at (" << x << ", " << y << ")\n";}
};// 叶子构件 - 圆
class Circle : public Graphic {int x, y;int radius;
public:Circle(int x, int y, int radius) : x(x), y(y), radius(radius) {}void move(int x, int y) override {this->x += x;this->y += y;}void draw() const override {std::cout << "Drawing a circle at (" << x << ", " << y << ") with radius " << radius << "\n";}
};// 容器构件 - 组合图形
class CompoundGraphic : public Graphic {std::vector<std::unique_ptr<Graphic>> children;
public:void add(std::unique_ptr<Graphic> graphic) {children.push_back(std::move(graphic));}void move(int x, int y) override {for (const auto& child : children) {child->move(x, y);}}void draw() const override {std::cout << "=== Drawing a compound graphic ===\n";for (const auto& child : children) {child->draw();}std::cout << "=== End of compound graphic ===\n";}
};int main() {auto all = std::make_unique<CompoundGraphic>();all->add(std::make_unique<Dot>(1, 2));all->add(std::make_unique<Circle>(5, 3, 10));auto group = std::make_unique<CompoundGraphic>();group->add(std::make_unique<Circle>(10, 10, 5));group->add(std::make_unique<Dot>(10, 10));all->add(std::move(group));all->add(std::make_unique<Dot>(20, 20));std::cout << "Initial drawing:\n";all->draw();all->move(5, 5);std::cout << "\nAfter moving (5,5):\n";all->draw();
}

示例3:组织架构系统

#include <iostream>
#include <vector>
#include <memory>
#include <string>// 抽象构件
class OrganizationUnit {
public:virtual ~OrganizationUnit() = default;virtual void display(int depth = 0) const = 0;virtual void add(std::unique_ptr<OrganizationUnit> unit) {throw std::runtime_error("Cannot add to a leaf unit");}virtual double getSalary() const = 0;
};// 叶子构件 - 员工
class Employee : public OrganizationUnit {std::string name;double salary;
public:Employee(const std::string& name, double salary) : name(name), salary(salary) {}void display(int depth = 0) const override {std::cout << std::string(depth * 2, ' ') << name << " (Salary: $" << salary << ")\n";}double getSalary() const override { return salary; }
};// 容器构件 - 部门
class Department : public OrganizationUnit {std::string name;std::vector<std::unique_ptr<OrganizationUnit>> units;
public:explicit Department(const std::string& name) : name(name) {}void display(int depth = 0) const override {std::cout << std::string(depth * 2, ' ') << "Department: " << name << " (Total Salary: $" << getSalary() << ")\n";for (const auto& unit : units) {unit->display(depth + 1);}}void add(std::unique_ptr<OrganizationUnit> unit) override {units.push_back(std::move(unit));}double getSalary() const override {double total = 0.0;for (const auto& unit : units) {total += unit->getSalary();}return total;}
};int main() {auto company = std::make_unique<Department>("ACME Corporation");auto engineering = std::make_unique<Department>("Engineering");engineering->add(std::make_unique<Employee>("John Doe", 85000));engineering->add(std::make_unique<Employee>("Jane Smith", 95000));auto qa = std::make_unique<Department>("Quality Assurance");qa->add(std::make_unique<Employee>("Bob Johnson", 75000));qa->add(std::make_unique<Employee>("Alice Williams", 80000));engineering->add(std::move(qa));company->add(std::move(engineering));auto marketing = std::make_unique<Department>("Marketing");marketing->add(std::make_unique<Employee>("Mike Brown", 90000));marketing->add(std::make_unique<Employee>("Sarah Davis", 88000));company->add(std::move(marketing));company->add(std::make_unique<Employee>("CEO", 250000));std::cout << "Company Structure:\n";company->display();std::cout << "\nTotal company salary: $" << company->getSalary() << std::endl;
}

示例4:UI组件系统

#include <iostream>
#include <vector>
#include <memory>
#include <string>// 抽象构件
class UIComponent {
public:virtual ~UIComponent() = default;virtual void render() const = 0;virtual void add(std::unique_ptr<UIComponent> component) {throw std::runtime_error("Cannot add to a leaf component");}
};// 叶子构件 - 按钮
class Button : public UIComponent {std::string label;
public:explicit Button(const std::string& label) : label(label) {}void render() const override {std::cout << "[Button: " << label << "]\n";}
};// 叶子构件 - 文本框
class TextBox : public UIComponent {std::string placeholder;
public:explicit TextBox(const std::string& placeholder) : placeholder(placeholder) {}void render() const override {std::cout << "[TextBox: " << placeholder << "]\n";}
};// 容器构件 - 面板
class Panel : public UIComponent {std::string title;std::vector<std::unique_ptr<UIComponent>> children;
public:explicit Panel(const std::string& title) : title(title) {}void render() const override {std::cout << "=== Panel: " << title << " ===\n";for (const auto& child : children) {child->render();}std::cout << "=== End of Panel ===\n";}void add(std::unique_ptr<UIComponent> component) override {children.push_back(std::move(component));}
};// 容器构件 - 窗口
class Window : public UIComponent {std::string title;std::vector<std::unique_ptr<UIComponent>> children;
public:explicit Window(const std::string& title) : title(title) {}void render() const override {std::cout << "**** Window: " << title << " ****\n";for (const auto& child : children) {child->render();}std::cout << "**** End of Window ****\n";}void add(std::unique_ptr<UIComponent> component) override {children.push_back(std::move(component));}
};int main() {auto loginWindow = std::make_unique<Window>("Login");auto formPanel = std::make_unique<Panel>("Login Form");formPanel->add(std::make_unique<TextBox>("Username"));formPanel->add(std::make_unique<TextBox>("Password"));auto buttonPanel = std::make_unique<Panel>("Actions");buttonPanel->add(std::make_unique<Button>("Login"));buttonPanel->add(std::make_unique<Button>("Cancel"));loginWindow->add(std::move(formPanel));loginWindow->add(std::move(buttonPanel));std::cout << "Rendering UI:\n";loginWindow->render();
}

这些示例展示了组合模式如何通过树形结构来表示部分-整体层次结构,使得客户端可以一致地处理单个对象和组合对象。组合模式特别适合用于构建递归结构,如文件系统、UI组件、组织结构等场景。

http://www.dtcms.com/a/317718.html

相关文章:

  • 基于spring boot的个人博客系统
  • tkwebview-tkinter的web视图
  • 解决云服务器端口无法访问的方法
  • java学习 leetcode24交换链表节点 200岛屿数量 +一些开发任务
  • Redis(七):Redis高并发高可用(主从复制)
  • JP3-4-MyClub后台前端(二)
  • C++、STL面试题总结(三)
  • 考研408_数据结构笔记(第四章 串)
  • 第五十一章:AI模型服务的“百变面孔”:WebUI/CLI/脚本部署全解析
  • 功能安全和网络安全的综合保障流程
  • Transformers简单介绍 - 来源于huggingface
  • 虚幻GAS底层原理解剖五 (AS)
  • 从案例学习cuda编程——线程模型和显存模型
  • git 清理submodule
  • PowerShell部署Windows爬虫自动化方案
  • 【ArcGIS】分区统计中出现Null值且Nodata无法忽略的问题以及shp擦除(erase)的使用——以NDVI去水体为例
  • DevOps时代的知识基座革命:Gitee Wiki如何重构研发协作范式
  • Unity轻量观察相机
  • 利用DeepSeek编写go语言按行排序程序
  • centos配置java环境变量
  • Go语言 单元测试
  • 后端服务oom
  • 商品详情数据的秒级更新如何运用京东 API 实现?
  • Debian系统更新实现
  • Docker国内可用镜像(2025.08.06测试)
  • 【QT】-windous 应用程序开机自启
  • 组合期权:跨式策略
  • 【数字图像处理系列笔记】Ch03:图像的变换
  • Node.js- express的基本使用
  • MyBatis增删改、RESTful API 风格、SpringAOP