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

C++设计模式——Composite组合模式

一,组合模式简介

真实世界中,像企业组织、文档、图形软件界面等案例,它们在结构上都是分层次的。将系统分层次的方式使得统一管理和添加不同子模块变得容易,在软件开发中,组合模式的设计思想和它们类似。

组合模式是一种结构型设计模式,该模式将对象组合成树状结构,以便于分层和统一管理。

组合模式用于为复杂的分层的系统结构定义基本的蓝图,并对外提供统一的接口,简化了系统组件的使用方法。

二,组合模式的结构

1.组件类(Component):声明了统一的抽象接口。它定义了Leaf类和Composite类的通用函数接口。

2.叶子节点类(Leaf):提供了Component类的接口实现,组合模式中的最小单元。

3.组合类(Composite):也提供了Component类的接口实现,其中包含多个Component对象。它对子组件进行了封装,使用客户端(Client)可以像操作单个组件一样使用整个组合。

对应UML类图:

三,组合模式代码样例

Demo1:先操作叶子节点,后操作主节点

#include <iostream>
#include <vector>class Component {
public:virtual void operation() const = 0;virtual ~Component() {}
};class Leaf : public Component {
public:Leaf(const std::string& name) : name_(name) {}virtual void operation() const override {std::cout << "Operation on leaf: " << name_ << std::endl;}
private:std::string name_;
};class Composite : public Component {
public:Composite(const std::string& name) : name_(name), children_{} {}void add(Component* component) {children_.push_back(component);}void operation() const override {for (const auto& child : children_) {child->operation();}std::cout << "Operation on composite: " << name_ << std::endl;}
private:std::vector<Component*> children_;std::string name_;
};int main() {Composite root("Composite Root");Leaf leaf1("Leaf 1");Leaf leaf2("Leaf 2");Leaf leaf3("Leaf 3");root.add(&leaf1);root.add(&leaf2);root.add(&leaf3);root.operation();return 0;
}

运行结果:

Operation on leaf: Leaf 1
Operation on leaf: Leaf 2
Operation on leaf: Leaf 3
Operation on composite: Composite Root

Demo2:先操作主节点,后操作叶子节点

#include <iostream>
#include <vector>class Component {
public:virtual ~Component() {}virtual void operation() const = 0;
};class Leaf : public Component {
public:Leaf(const std::string& name) : name(name) {}virtual void operation() const override {std::cout << "Operation on leaf: " << name << '\n';}
private:std::string name;
};class Composite : public Component {
public:Composite(const std::string& name) : Component(), children(), _name(name) {}void add(Component* component) {children.push_back(component);}void remove(Component* component) {children.erase(std::remove(children.begin(),children.end(),component),children.end());}void operation() const override {std::cout << "Operation on composite: " << _name << '\n';for (auto& child : children)child->operation();}private:std::vector<Component*> children;std::string _name;
};int main() {Composite root("Composite1");root.add(new Leaf("Leaf1"));root.add(new Leaf("Leaf2"));root.add(new Composite("Composite2"));root.add(new Leaf("Leaf3"));root.operation();return 0;
}

运行结果:

Operation on composite: Composite1
Operation on leaf: Leaf1
Operation on leaf: Leaf2
Operation on composite: Composite2
Operation on leaf: Leaf3

四,组合模式的应用场景

平面设计软件开发:在Photoshop等应用程序中,形状、线条和文本等图形元素可以组合成复杂的设计。

文件系统:使用组合模式来表示文件和目录,从而形成可以统一处理和查询的分层结构。

UI框架开发:基于组合模式,可以让UI组件(如按钮、标签和面板等)组合成复杂的布局或界面。

文档编辑器:使用组合模式来实现文档的段落和文本等层次结构。

企业软件开发:企业软件通常对组织结构进行建模,包括部门、团队和员工。组合模式用于实现组织单位及其内部员工的层次结构。

五,组合模式的优缺点

组合模式的优点:

1.便于维护和重构,修改单个组件的代码不会影响整个系统的功能。

2.有树形结构的先天优势,可以很方便地统一添加、删除或修改子节点。

3.通过拆分子组件,提高了模块间的独立性和可重用性。

4.符合"单一职责原则",组合中的每个对象只关注自己的职责,不需要考虑整个组合中的功能配合。

组合模式的缺点:

1.性能开销大,该模式涉及了对象的动态创建和管理,频繁操作可能会引起性能问题。

2.增加了代码的复杂度,当组合的层次过深的时候,代码的结构会很复杂。

3.类型安全问题,当管理多个组件对象时,可能需要额外的类型转换编码。

六,代码实战

代码实战:基于组合模式实现的文件系统

#include <iostream>
#include <bits/stdc++.h>class FileSystemComponent {
public:virtual void display() const = 0;
};class File : public FileSystemComponent {
public:File(const std::string& name, int size): name(name), size(size){}void display() const override{std::cout << "File: " << name <<" (" << size << " bytes)" <<std::endl;}
private:std::string name;int size;
};class Directory : public FileSystemComponent {
public:Directory(const std::string& name): name(name){}void display() const override{std::cout << "Directory: " << name << std::endl;for (const auto& component : components) {component->display();}}void addComponent(FileSystemComponent* component){components.push_back(component);}
private:std::string name;std::vector<FileSystemComponent*> components;
};int main()
{FileSystemComponent* file1= new File("document.txt", 1024);FileSystemComponent* file2= new File("image.jpg", 2048);Directory* directory = new Directory("My Documents");directory->addComponent(file1);directory->addComponent(file2);directory->display();return 0;
}

运行结果:

Directory: My Documents
File: document.txt (1024 bytes)
File: image.jpg (2048 bytes)

七,参考阅读

https://refactoring.guru/design-patterns/composite
https://www.geeksforgeeks.org/composite-method-software-design-pattern/
https://www.geeksforgeeks.org/composite-design-pattern-in-java/
http://www.lryc.cn/news/379096.html

相关文章:

  • Android提供的LruCache类简介(1)
  • 【分布式系列】分布式锁timeout了怎么办?
  • System.getProperty()方法总结
  • 大型语言模型在AMD GPU上的推理优化
  • Apple - Core Foundation Design Concepts
  • lua中的lfs库介绍
  • PyCharm 快捷键积累
  • C++进阶之AVL树
  • sizeof 和 strlen 比较
  • 音视频开发—FFmpeg 打开摄像头进行RTMP推流
  • D触发器(D Flip-Flop)与D锁存器(D Latch)
  • JDK19特性
  • sql语句中常用的函数有那些
  • odoo17 小变更3 Warning、 “attrs “和 “states “不再用
  • Unity3d 游戏暂停(timeScale=0)引起的deltaTime关联的系列问题解决
  • 服务端代码编写中MySql大小写在Java中报错问题解决
  • CRMEB 多店商品详情页装修说明
  • Redis-使用 jedis 操作数据
  • 简说PIP换源
  • django学习入门系列之第三点《CSS基础样式介绍2》
  • 分布式光纤测温DTS在工程现场中稳定性与可靠性如何?
  • PHP多线程模块parallel的编译安装和多线程编程演示
  • 记录grid布局属性
  • 12.爬虫---PyMysql安装与使用
  • VS2022遇到的两个问题
  • 【Android14 ShellTransitions】(六)SyncGroup完成
  • 技术管理转型之战:决策之道-管理中的智慧与策略
  • Shell脚本:条件语句(if、case)
  • 在Linux上为Windows目标配置Qt交叉编译
  • Introduction to linear optimization 第 2 章课后题答案 11-15