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

C++设计模式---组合模式

1、介绍

        组合模式(Composite)是一种结构型设计模式,也被称为部分-整体模式。它将复杂对象视为由多个简单对象(称为“组件”)组成的树形结构,这些组件能够共享相同的行为。每个组件都可能包含一个或多个子组件,而不需要了解子组件的具体类型。

在组合模式中,有三个关键角色:

        (1)组件(Composite):这个抽象类或接口定义了所有组件都具有的公共行为。它通常有一个或多个方法来访问其子组件,并且可以包含一个指向子组件的指针数组。

        (2)具体组件(Leaf):这是没有子组件的组件,它们直接实现了组件接口。这些是组合模式的叶子节点,不包含其他元素。

        (3)复合组件(Composite):这是有子组件的组件,它们除了实现组件接口外,还负责维护子组件的列表,以及调用相应的方法对它们进行操作。

组合模式的优点:

        (1)支持动态扩展和灵活的层次结构。

        (2)降低组件间的耦合度,使得代码更易于理解和维护。

        (3)可以统一处理所有类型的组件,无论是简单的还是复杂的。

2、示例

#include <iostream>
#include <string>
#include <vector>// 抽象的组件类Element 描写全部部件共同拥有的行为
class Element
{
public:Element(const std::string& name): m_name(name){}virtual ~Element(){}virtual void eat() = 0;virtual void add(Element *) = 0;virtual void remove(Element *) = 0;virtual const std::string& getName(){return m_name;}
protected:std::string m_name;
};// 具体组件类,叶子构件 Apple类
class Apple : public Element
{
public:Apple(const std::string& name): Element(name){}virtual ~Apple(){std::cout << "~Apple()" << std::endl;}void eat(){std::cout << "eat fruit type is apple" << std::endl;}void add(Element *pcomt){}void remove(Element *pcomt){}
};// 具体组件类,叶子构件 Banana类
class Banana : public Element
{
public:Banana(const std::string& name): Element(name){}virtual ~Banana(){std::cout << "~Banana()" << std::endl;}void eat(){std::cout << "eat fruit type is banana " << std::endl;}void add(Element *pcomt){}void remove(Element *pcomt){}
};// 具体组件类,叶子构件 Pear类
class Pear : public Element
{
public:Pear(const std::string& name): Element(name){}virtual ~Pear(){std::cout << "~Pear()" << std::endl;}void eat(){std::cout << "eat fruit type is pear" << std::endl;}void add(Element *pcomt){}void remove(Element *pcomt){}
};// 复合组件类 容器构件类 PlateComposite水果盘
class PlateComposite : public Element
{
public:PlateComposite(const std::string& name): Element(name){}virtual ~PlateComposite(){std::cout << "~PlateComposite()" << std::endl;std::vector<Element *>::iterator it = _vecComp.begin();while (it != _vecComp.end()) {if (*it != NULL){std::cout << "----delete " << (*it)->getName() << "----" << std::endl;delete *it;*it = NULL;}_vecComp.erase(it); it = _vecComp.begin();}}void eat(){for(auto iter : _vecComp){iter ->eat();}}void add(Element *pcomt){_vecComp.push_back(pcomt);}void remove(Element *pcomt){for (std::vector<Element *>::iterator it = _vecComp.begin(); it != _vecComp.end(); ++it){if ((*it)->getName() == pcomt->getName()){if (*it != NULL){delete *it;*it = NULL;}_vecComp.erase(it);break;}}}
private:std::vector<Element *> _vecComp;
};int main() 
{ Element *obj1 = new Apple("apple");Element *obj2 = new Banana("banana");Element *plate1 = new PlateComposite("zuhe_1");plate1->add(obj1);plate1->add(obj2);plate1->eat();std::cout << "-----------------------------------------------" << std::endl;Element *obj3 = new Pear("pear");Element *plate2 = new PlateComposite("zuhe_2");plate2->add(obj3);plate2->eat();std::cout << "-----------------------------------------------" << std::endl;plate1->add(plate2);   // 将组合zuhe_2添加到组合zuhe_1中plate1->eat();std::cout << "-----------------------------------------------" << std::endl;plate1->remove(obj1);plate1->eat();std::cout << "-----------------------------------------------" << std::endl;// delete obj1;// delete obj2;if(nullptr != plate1){delete plate1;plate1 = nullptr;}return 0; 
} 

结果:

eat fruit type is apple
eat fruit type is banana 
-----------------------------------------------
eat fruit type is pear
-----------------------------------------------
eat fruit type is apple
eat fruit type is banana 
eat fruit type is pear
-----------------------------------------------
~Apple()
eat fruit type is banana 
eat fruit type is pear
-----------------------------------------------
~PlateComposite()
----delete banana----
~Banana()
----delete zuhe_2----
~PlateComposite()
----delete pear----
~Pear()

http://www.lryc.cn/news/372064.html

相关文章:

  • 工厂方法模式(大话设计模式)C/C++版本
  • [NCTF 2018]flask真香
  • 性能测试3【搬代码】
  • <tesseract><opencv><Python>基于python和opencv,使用ocr识别图片中的文本并进行替换
  • 海南云亿商务咨询有限公司解锁抖音电商新纪元
  • arm64架构 统信UOS搭建PXE无盘启动Linux系统(麒麟桌面为例)
  • SpringBoot 实现 阿里云语音通知(SingleCallByTts)
  • IDEA 连接GitHub仓库并上传项目(同时解决SSH问题)
  • vue/react/js 常用的原生获取当前页面的url网址的相关方法
  • java-final 关键字
  • ARM32开发--IIC软实现
  • 在有向无环图(DAG)中实现拓扑排序与最短路径和最长路径算法
  • SQLServer按照年龄段进行分组查询数据
  • 开放式耳机哪个品牌质量比较好?2024高性价比机型推荐!
  • Blender骨骼创建
  • DevExpress WPF中文教程:Grid - 如何完成列和编辑器配置(设计时)?
  • 高考完的三个月想自学点编程,有没有什么建议
  • 运维开发(DevOps):加速软件交付的关键方法
  • Vue前端环境搭建:从四个方面、五个方面、六个方面和七个方面深度解析
  • 农业领域科技查新点提炼方法附案例!
  • 【Bazel入门与精通】 rules之属性
  • Elementor无需第三方插件实现高级下拉菜单/巨型菜单
  • 【数学】什么是傅里叶变换?什么是离散傅里叶变换?什么是拉普拉斯变换?
  • opencv安装笔记 各种平台
  • 前端开发中的热更新原理
  • unix环境高级编程第2版:深入探索UNIX编程的奥秘
  • 力扣42 接雨水
  • 【代码随想录】【算法训练营】【第35天】[134]加油站 [135]分发糖果 [860]柠檬水找零 [406]根据身高重建队列
  • Talk|新加坡国立大学贾鑫宇:适用于高自由度机器人的运动控制器
  • 【npm】console工具(含胶囊,表格,gif图片)