C++设计模式 - 组合模式(Composite)

2023-11-09

数据结构模式

  • 常常有一-些组件在内部具有特定的数据结构,如果让客户程序依赖这些特定的数据结构,将极大地破坏组件的复用。这时候,将这些特定数据结构封装在内部,在外部提供统一的接口,来实现与特定数据结构无关的访问,是一种行之有效的解决方案。

典型模式

  • Composite
  • Iterator
  • Chain of Resposibility

Composite

动机( Motivation )

  • 在软件在某些情况下,客户代码过多地依赖于对象容器复杂的内部实现结构,对象容器内部实现结构(而非抽象接口)的变化将引起客户代码的频繁变化,带来了代码的维护性、扩展性等弊端。
  • 如何将“客户代码与复杂的对象容器结构”解耦?让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器?

模式定义.

将对象组合成树形结构以表示“部分整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性(稳定)。

结构

在这里插入图片描述

要点总结

  • Composite模式采用树形结构来实现普遍存在的对象容器,从而,将”一对多”的关系转化为“一对一”的关系使得客户代码可以一致地(复用)处理对象和对象容器,无需关心处理的是单个的对
    象,还是组合的对象容器。
  • 将“客户代码与复杂的对象容器结构”解耦是Composite的核心思想,解耦之后,客户代码将与纯粹的抽象接口一”而非对象容器的内部实现结构二发生依赖 ,从而更能“应对变化”
  • Composite模式在具体实现中,可以让父对象中的子对象反向追溯;如果父对象有频繁的遍历需求,可使用缓存技巧来改善效率。

cpp

#include<list>
#include<string>
#include<memory>
#include<algorithm>
#include<iostream>
class Component
{
protected:
    std::string name;
public:
    Component(std::string str) :name(str) {}
    virtual void display() = 0;
    virtual void add(Component*) = 0;
    virtual void remove(Component*) = 0;
    virtual ~Component() {}
};

class Composite:public Component
{
private:
    std::list<std::shared_ptr<Component>>elements;
public:
    Composite(std::string str) :Component(str) {}
    void add(Component* element)
    {
        auto it = std::find_if(elements.begin(), elements.end(), 
            [element](std::shared_ptr<Component>ptr) {return element == ptr.get(); });
        if (it == elements.end())
        {
            elements.push_back(std::shared_ptr<Component>(element));
        }
    }
    void remove(Component* element)
    {
        auto it = std::find_if(elements.begin(), elements.end(),
            [element](std::shared_ptr<Component>ptr) {return element == ptr.get(); });
        if (it == elements.end())
        {
            return;
        }
        elements.erase(it);
    }
    void display()
    {
        for (auto it = elements.cbegin(); it != elements.cend(); ++it)
        {
            (*it)->display();   //多态调用
        }
    }
};

class Leaf : public Component 
{
public:
    Leaf(std::string str) :Component(str) {}
    void display()
    {
        std::cout << name << std::endl;
    }
    void add(Component* element)
    {
        std::cout << "Leaf cannot add" << std::endl;
    }
    void remove(Component* element)
    {
        std::cout << "Leaf cannot remove" << std::endl;
    }
};


int main()
{
    Component* p = new Composite("北京");
    p->add(new Leaf("紫荆城"));
    p->add(new Leaf("朝阳区"));
    Component* p1 = new Composite("郑州");
    p1->add(new Leaf("郑大"));
    p1->add(new Leaf("。。。"));
    p->add(p1);
    p->display();
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++设计模式 - 组合模式(Composite) 的相关文章

  • is_integral 与 is_integer:其中之一是多余的吗?

    是积分 http en cppreference com w cpp types is integral and 是整数 http en cppreference com w cpp types numeric limits is inte
  • 如何将不记名令牌发送到 ASP NET MVC 5 中的视图?

    我有一个 NET MVC and WEB API项目 我想打电话给WEB API controllers来自 javascript 但我没有找到将令牌发送到我的视图的方法 我想添加bearer token in Viewbag变量 使用以下
  • 为什么这个 oracle 批量插入不起作用?

    我正在尝试将一些数据批量插入到 oracle 数据库中 我按照文档中的示例进行操作 this DataBaseAccess new OracleConnection connString var dataAdapter new Oracle
  • C# 并行与并行线程代码性能

    我一直在测试 System Threading Parallel 与线程的性能 我很惊讶地发现并行比线程花费更长的时间来完成任务 我确信这是由于我对并行的了解有限 我刚刚开始阅读 我想我会分享一些片段 如果有人可以向我指出并行代码比线程代码
  • 比较 LINQ to SQL 中的两个日期

    我有一个数据库 其中有一个名为会议的表 会议日期使用以下格式存储在此表中 May 2nd 2011 例如 格式为5 2 2011 我的要求是获取两个日期 例如 2011 年 4 月 25 日和 2011 年 5 月 2 日 之间的会议 并编
  • NHibernate IQueryable 集合作为 root 的属性

    我有一个根对象 它有一个集合属性 例如 I have a Shelf object that has Books Now public class Shelf public ICollection
  • 如何从Web JavaScript应用程序获取桌面C#程序中的变量

    我遇到一个问题 有两个应用程序 一种是 C 中的桌面应用程序 另一种是 javascript 中的 Web 应用程序 运行桌面应用程序中的一些变量或信息需要传输到Web应用程序 有谁知道如何解决这个问题 有人愿意提供更多细节来解决这个问题吗
  • 三种 System.Drawing 方法表现出缓慢的绘制或闪烁:解决方案?或其他选择?

    我正在通过 System Drawing 进行一些绘图 但遇到了一些问题 我将数据保存在队列中 并将该数据绘制 绘制 到三个图片框中 此方法填充图片框 然后滚动图形 所以不要在以前的绘图上绘制 并且逐渐看起来更混乱 我找到了两种绘制图表的解
  • Nuget - 对象引用未设置为对象的实例

    我在 vs 2015 中遇到了 nuget 包管理器的问题 像Unity这样的一些包已经安装没有问题了 某些软件包 例如 EF 在安装时出现问题 像 Automapper 这样的一些软件包也有同样的问题 但是当我安装这个软件包的另一个版本时
  • 我可以对(非成员)函数使用部分模板特化吗?

    我试图在 非成员 函数上使用部分模板专业化 但我在语法上遇到了问题 我在 StackOverflow 中搜索了其他部分模板专业化问题 但这些问题涉及类或成员函数模板的部分专业化 作为起点 我有 struct RGBA RGBA uint8
  • Request.Form 和 Request.QueryString 之间的区别?

    有人可以告诉我两者之间的确切区别吗Request Form and Request QueryString 我知道一个区别 比如 如果HTTP请求方式为POST 则用户提交的数据在申请表 收藏 如果HTTP请求方法是GET 则用户提交的数据
  • 类型别名和不完整类型

    我可能已经超出了解决这个本应简单的问题的范围 我在这里开始这个问题 在编译时获取基类的类型 https stackoverflow com questions 17735852 getting type of a base class at
  • 为什么未到达的 try-catch 块会增加运行时间?

    我目前正在创建自己的容器库 但我已经看到无法访问 if 语句无效 try catch阻止增加运行时间 这是我的测试 Vector cpp template
  • 为什么必须通过 this 指针访问模板基类成员?

    如果下面的类不是模板 我可以简单地拥有x in the derived班级 但是 通过下面的代码 我have to use this gt x Why template
  • #define 内存地址声明

    这个 define 语句有什么作用 它用于定义内存地址 但我不明白 uint32 t 部分 define GPxDAT uint32 t 0x6FC0 通常用于访问映射到地址空间的硬件寄存器 或者一些特定的内存地址 硬件寄存器应定义为vol
  • 如何创建和使用类箭头运算符? [复制]

    这个问题在这里已经有答案了 因此 在到处研究之后 我似乎找不到如何创建类箭头运算符 即 class Someclass operator gt 我只需要知道如何使用它并正确使用它 它的输入是什么 它返回什么 我如何正确地声明 原型化它 运算
  • 返回 ICollection 而不是 List 的真正优势是什么? [复制]

    这个问题在这里已经有答案了 我读过几篇博客文章 提到对于公共 API 我们应该始终返回 ICollection 或 IEnumerable 而不是 List 返回 ICollection 而不是 List 的真正优势是什么 Thanks 复
  • C# 3.0 中自动属性和公共字段的区别

    我无法理解为什么 C 3 0 中存在自动实现的属性语言功能 当你说的时候有什么区别 public string FirstName than public string FirstName get set 因为它们在生成的 IL 代码 和机
  • char[length]初始化并处理

    我定义了一个字符数组 char d 6 如果我在以下方面有误 请纠正我 此时没有为变量分配内存d 现在我要初始化它 d aaaaa 这种初始化之后 就不需要释放内存了 它将自动完成 我怎么知道是否char 被初始化了吗 我正在寻找类似的模式
  • DataGridView 捕获用户行选择

    我在处理选择时遇到问题DataGridView 我的网格视图包含一个金额列 表单上有一个文本框 应显示所选网格视图行的总数 因此 我需要在用户选择 取消选择 gridview 行时捕获事件并相应地计算 添加 减去 金额 我找到了两种方法 使

随机推荐

  • 我们为什么选择CentOS

    服务器操作系统大多采用Unix和Linux操作系统 而Linux发行版本系统中 多使用CentOS Redhat Ubuntu Gentoo Debian 而这些发行版本可以大体分为两类 一类是商业公司维护的发行版本 一类是社区组织维护的发
  • Spark Shuffle 中 JVM 内存使用及配置内幕详情

    引言 Spark 从1 6 x 开始对 JVM 的内存使用作出了一种全新的改变 Spark 1 6 x 以前是基于静态固定的JVM内存使用架构和运行机制 如果你不知道 Spark 到底对 JVM 是怎么使用 你怎么可以很有信心地或者是完全确
  • 面试官的技术面试技巧与步骤

    面试官进行技术面试的常用技巧与步骤 面试需求 解读人员需求与岗位说明 了解岗位需求和工作内容 明确岗位对人员的知识技能 工作经验和基本素质要求 面前准备 分析应聘者简历 判断人员需求 岗位说明与应聘人员的匹配度 发现需进一步确认的信息 分析
  • 基于产品的RFM模型的k-means聚类分析

    首先我们可以看看数据集的数据形态 导入rfm数据 查看数据的统计学参数 df pd read csv rfm csv df describe 在实施Kmeans聚类之前 我们必须检查这些关键k means假设 变量对称分布 不倾斜 具有相同
  • Ubuntu安装Vmware tools

    点击vmware右上角虚拟机的下拉菜单中点击 安装 VMware Tools 然后在桌面上会有一个压缩包 右击打开当前文件夹 重命名这个压缩包为vmwaretools tar gz 在当前文件夹中打开terminal cp vmwareto
  • 机器学习算法(二十三):DTW(Dynamic Time Warping,动态时间调整)

    目录 1 DTW 动态时间调整 2 算法的实现 3 例子 4 python实现 5 DTW的加速算法FastDTW 5 1 标准DTW算法 5 2 DTW常用加速手段 5 3 FastDTW 1 DTW 动态时间调整 动态时间调整算法是大多
  • java pv uv_前端数据收集(pv/uv)

    所谓web 即使你我素未谋面 便知志趣相投 足不出户 亦知世界大 01 什么是PV UV 网站流量分析 是指在获得网站访问量基本数据的情况下对有关数据进行统计 分析 从中发现用户访问网站的规律 并将这些规律与网络营销策略等相结合 从而发现目
  • Cadence Allegro(8):生成网络报表(Netlist)

    Cadence Allegro 8 生成网络报表 Netlist 前提摘要 PCB设计软件版本 原理图设计 Pad Designer 16 6 PCB设计 PCB Editor 16 6 个人说明 限于时间紧迫以及作者水平有限 本文错误 疏
  • selenium chrome java 无头模式使用cdp设置navigator.permission

    Chrome Devtools Protocol 前提 chromium无头模式下和gui模式是不同的 userData无法指定 也无法通过模拟点击alert授权 或者进入chrome settings 通过selenium控制授权 因为无
  • 奶牛碑文。

    include
  • 八大数据结构

    八大数据结构 数据结构分类 1 数组 2 栈 3 队列 4 链表 5 树 6 散列表 7 堆 8 图 1 数组 数组是可以再内存中连续存储多个元素的结构 在内存中的分配也是连续的 数组中的元素通过数组下标进行访问 数组下标从0开始 例如下面
  • ORACLE 生成唯一id

    1 创建一个序列 create sequence id 序列名称 increment by 1 以1递增 start with 1 从1开始 maxvalue 999999999 最大值 2 创建函数调用上边创建的序列 CREATE FUN
  • PyCharm 使用教程:PyCharm常用技巧指南,轻松学会

    在 PyCharm 中 打开已有的项目有 3 种方式 欢迎界面中选择open 菜单栏中选择 File gt open 打开远程 Git 的项目 在 PyCharm 中 打开已有的项目可以在第一次打开的欢迎界面中选择open来打开你电脑中已经
  • 【‘XXX‘ is declared but its value is never read.】

    遇到问题了 引入一个弹窗组件 已经import了 也在template中写了弹窗组件 但是弹窗就是不出来 1 看看报错信息 没啥报错 2 看看代码 import中的代码暗淡了 鼠标移入出现上面的报错 突然想起来没有在component中写入
  • breach靶场练习详细全过程

    补充 桥接 nat host only三种网络模式的区别 模式 特点 场景 bridge桥接模式 特点 虚拟机使用物理机的网卡 不用虚拟网卡 占用一个ip 需要配置ip以后才可以访问互联网 场景 虚拟机需要连接实体设备的时候 nat网络地址
  • 最好用的 6 个 React Tree select 树形组件测评与推荐

    本文完整版 最好用的 6 个 React Tree select 树形组件测评与推荐 React Tree select 树形组件 1 React Sortable Tree 全功能 树状单选多选 可拖拽 过滤搜索 多种主题可选 2 Rea
  • android开发浏览器!写给1-3年安卓程序员的几点建议,聪明人已经收藏了!

    前言 作为一个程序员 如果你在新知识 新技术面前仍一无所知 依然吃着十多年前的老本 那你在知识技术上肯定落伍 如果又未能进入管理层面 那你肯定就会被长江的后浪拍在沙滩上了 而不少与时俱进 善于学习的程序员他们仍是行业的中坚力量 这只是说明当
  • 面试利器(二)-------插入排序(直接插入排序和希尔排序(Shell排序))

    一 直接插入排序 抓住关键字 插入 1 基本思想 顺序地把待排序的序列中的各个数据按其关键字的大小 插入到已排序的序列的适当位置 2 运行过程 1 将待排序序列的第一个数据看做一个有序序列 把第二个数据到最后一个数据当成是未排序序列 2 从
  • openblas第一弹:openblas 使用说明和常用接口介绍

    openblas 使用说明 openblas 是一个开源的矩阵计算库 包含了诸多的精度和形式的矩阵计算算法 就精度而言 包括float和double 两种数据类型的数据 其矩阵调用函数也是不一样 不同矩阵 其计算方式也是有所不同 姑且认为向
  • C++设计模式 - 组合模式(Composite)

    数据结构模式 常常有一 些组件在内部具有特定的数据结构 如果让客户程序依赖这些特定的数据结构 将极大地破坏组件的复用 这时候 将这些特定数据结构封装在内部 在外部提供统一的接口 来实现与特定数据结构无关的访问 是一种行之有效的解决方案 典型