Composite——设计模式学习笔记

2023-11-02

Composite模式

一 意图

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

二 动机

  绘图编辑器和图形捕捉系统图形应用程序中,总是存在简单的图形到简单的组件再到复杂的组件,

但他们在本质上都是图形(各种基本的图形组合或者递归组合)。

这可以分成两个部分:基本图元和组件图形。对于基本的图元可以单独定义类;对于组件图形可以使用图元容器(Container)。

  结果就是:在使用时,对于同样的都是图形的图元和组件必须加以区分对待(图元对象Or容器对象)。对于庞大的图形系统,这无疑是非常复杂的!

  解决方法:Composite模式递归组合,实现系统对图元还是组件都一致性对待。

      

对于Line或者Rectangle或者Picture都是Graphic,都具有相同的Graphic属性。

但对于Picture来说它是组合基本图元的方式组成的组件,本身会具有新的特性。

所以在Graphic图形中存在派生类组件的结构:

    

      

三 适用性及其结构

1 表示对象的部-整体层次结构

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

3 结构:

      

Component:为组合中的对象生命接口

      在适当情况下,实现所有类共有的接口的缺省行为

      声明一个接口用于访问和管理Component的子组件

      在递归结构中定义一个接口,用于访问一个父部件。

Leaf:在组合中表示叶节点对象

Composite:定义所有子部件的行为,实现与子部件相关的操作。

Composite实现任意组合方式构建定制新的Component。

4 性能分析

  Leaf和Composite同为Component,实际上之间是区别,Composite是各个Component的组合,

需要对各个Component进行维护,Leaf是不需要这些维护的。

所以这些维护接口是Composite自身提供还是Component提供这些维护的接口,比如:addChild,removeChild等。

  透明性:由基类Component提供所有Composite需要的基本一些接口管理其中的ChildComponent,

如addChild,removeChild等,这样就Leaf或者Composite具有一致性,而在客户端无需区分Leaf还是Composite。

  安全性:基类只提供Leaf相关的接口,作为Composite需要管理器中的ChildComponent需要自己提供。

保证Leaf的操作安全性。这样导致Leaf和Composite的不一致性需要区别对待,会造成系统的复杂性。

         这个在应用中我觉得,如果我们大量的操作都是基于Leaf的直接使用,而很少用到Composite,可以采取安全性,

但是这造成的结果就是:扩展性非常差。但通常在使用中大多数都是基于Composite方式,便于扩展和代码重用,

所以对ChildComponent的管理是非常重要的。在系统中都可以随处可见透明性的Composite模式,以构建一颗树形的对象模型。

 

四 代码实现

以电脑主板为例,电脑主板包括:CPU,内存,扩展槽,芯片组,时钟发生器,IDE接口和软驱,电源模块,I/O接口……

选取其中的:CPU,芯片组,I/O接口为例

1 Equicpment基类

View Code
/*----------------------------------------------------------------*/
/* class Equipment */
/*----------------------------------------------------------------*/
class Equipment
{
#define EQUIP_MAX_NUM (5)
public:
Equipment()
{
cout<<" Equipment constructor "<<endl;
for (int i = 0 ; i < EQUIP_MAX_NUM; i++)
{
m_equip[i] = NULL;
}
}
void addChildEquip(Equipment* equip)
{
for (int i = 0 ; i < EQUIP_MAX_NUM; i++)
{
if(m_equip[i] == NULL)
{
m_equip[i] = equip;
break;
}
}
}
void removeChildEquip(Equipment* equip)
{
for (int i = 0 ; i < EQUIP_MAX_NUM; i++)
{
if(m_equip[i] == equip)
{
m_equip[i] = NULL;
break;
}
}
}
void start()
{
for (int i = 0 ; i < EQUIP_MAX_NUM; i++)
{
if (m_equip[i] != NULL)
{
m_equip[i]->startEquipment();
}
}
}
virtual void startEquipment()
{
cout<<"Equipment startEquipment"<<endl;
}
private:
Equipment* m_equip[EQUIP_MAX_NUM];

};

2 Chip基类

View Code
/*----------------------------------------------------------------*/
/* class Chip */
/*----------------------------------------------------------------*/
class Chip: public Equipment
{
public:
Chip()
{
cout<<" Chip constructor "<<endl;
}
virtual void startEquipment()
{
cout<<" Chip startEquipment "<<endl;
}
};

3 Cpu部分

View Code
//CPU部分
/*
----------------------------------------------------------------*/
/* class CpuProcessor */
/*----------------------------------------------------------------*/
class CpuProcessor: public Chip
{
public:
CpuProcessor()
{
cout<<" CpuProcessor constructor "<<endl;
}
virtual void startEquipment()
{
cout<<" CpuProcessor startEquipment "<<endl;
}
};

/*----------------------------------------------------------------*/
/* class CpuSocket */
/*----------------------------------------------------------------*/
class CpuSocket: public Equipment
{
public:
CpuSocket()
{
cout<<" CpuSocket constructor "<<endl;
}
virtual void startEquipment()
{
cout<<" CpuSocket startEquipment "<<endl;
}
};

/*----------------------------------------------------------------*/
/* class CpuEquipment */
/*----------------------------------------------------------------*/
class CpuEquipment: public Equipment
{
public:
CpuEquipment()
{
cout<<" CpuEquipment constructor "<<endl<<endl;
}
void addChildCpu()
{
cout<<"-------------------addChildCpu-------------------"<<endl;
cpu = new CpuProcessor();
slot = new CpuSocket();

this->addChildEquip(cpu);
this->addChildEquip(slot);
}

virtual void startEquipment()
{
this->start();
cout<<" CpuEquipment startEquipment "<<endl<<endl;
}
private:
CpuProcessor* cpu;
CpuSocket* slot;
};

4 ChipSet部分

View Code
//ChipSet芯片组
/*
----------------------------------------------------------------*/
/* class GraphicsChip */
/*----------------------------------------------------------------*/
class GraphicsChip: public Chip
{
public:
GraphicsChip()
{
cout<<" GraphicsChip constructor "<<endl;
}
virtual void startEquipment()
{
cout<<" GraphicsChip startEquipment "<<endl;
}
};
/*----------------------------------------------------------------*/
/* class SoundChip */
/*----------------------------------------------------------------*/
class SoundChip: public Chip
{
public:
SoundChip()
{
cout<<" SoundChip constructor "<<endl;
}
};
/*----------------------------------------------------------------*/
/* class ChipSet */
/*----------------------------------------------------------------*/
class ChipSet: public Equipment
{
public:
ChipSet()
{
cout<<" ChipSet constructor "<<endl<<endl;
}
void addChildChip()
{
cout<<"-------------------addChildChip-------------------"<<endl;
GraphicsChip* gChip = new GraphicsChip();
SoundChip* sChip = new SoundChip();
this->addChildEquip(gChip);
this->addChildEquip(sChip);
}
virtual void startEquipment()
{
this->start();
cout<<" ChipSet startEquipment "<<endl<<endl;
}
private:

};

5 I/O接口部分

View Code
//I/O接口
/*
----------------------------------------------------------------*/
/* class IOEquipment */
/*----------------------------------------------------------------*/
class IOEquipment: public Equipment
{
public:
IOEquipment()
{
cout<<" IOEquipment constructor "<<endl;
}
virtual void startEquipment()
{
cout<<" IOEquipment startEquipment "<<endl;
}
};
/*----------------------------------------------------------------*/
/* class KeyboardIO */
/*----------------------------------------------------------------*/
class KeyboardIO: public IOEquipment
{
public:
KeyboardIO()
{
cout<<" KeyboardIO constructor "<<endl;
}
virtual void startEquipment()
{
cout<<" KeyboardIO startEquipment "<<endl;
}
};
/*----------------------------------------------------------------*/
/* class MouseIO */
/*----------------------------------------------------------------*/
class MouseIO: public IOEquipment
{
public:
MouseIO()
{
cout<<" MouseIO constructor "<<endl;
}
virtual void startEquipment()
{
cout<<" MouseIO startEquipment "<<endl;
}
};
/*----------------------------------------------------------------*/
/* class UsbIO */
/*----------------------------------------------------------------*/
class UsbIO: public IOEquipment
{
public:
UsbIO()
{
cout<<" UsbIO constructor "<<endl;
}
virtual void startEquipment()
{
cout<<" UsbIO startEquipment "<<endl;
}
};

/*----------------------------------------------------------------*/
/* class IOEquipmentSet */
/*----------------------------------------------------------------*/
class IOEquipmentSet: public Equipment
{
public:
IOEquipmentSet()
{
cout<<" IOEquipmentSet constructor "<<endl<<endl;
}
void addChildIO()
{
cout<<"-------------------addChildIO-------------------"<<endl;
KeyboardIO* kIO = new KeyboardIO();
MouseIO* mIO = new MouseIO();
UsbIO* uIO = new UsbIO();

this->addChildEquip(kIO);
this->addChildEquip(mIO);
this->addChildEquip(uIO);
}
virtual void startEquipment()
{
this->start();
cout<<" IOEquipmentSet startEquipment "<<endl<<endl;
}
};

6 MotherboardEquipment 主板

View Code
//主板
/*
----------------------------------------------------------------*/
/* class IOEquipmentSet */
/*----------------------------------------------------------------*/
class MotherboardEquipment: public Equipment
{
public:
MotherboardEquipment()
{
cout<<" MotherboardEquipment constructor "<<endl<<endl;
}
void addAllChildEquip()
{
cout<<"-------------------addAllChildEquip-------------------"<<endl;
CpuEquipment* cpuEquip = new CpuEquipment();
cpuEquip->addChildCpu();

ChipSet* chipEquip = new ChipSet();
chipEquip->addChildChip();

IOEquipmentSet* ioEquip = new IOEquipmentSet();
ioEquip->addChildIO();

this->addChildEquip(cpuEquip);
this->addChildEquip(chipEquip);
this->addChildEquip(ioEquip);
}
};

例子可能并非很完善和合理,仅仅是为了演示一下Composite模式。

五 实例分析

         将以手机上屏幕显示控件为例。控件涉及到UI显示布局和消息传递处理(按键触屏)

      

      

在Frame类中通过众多基类指针,将所有的对象组成一个树形结构。有助于对象管理和内存管理。

如果父类对象释放那么其子对象没有存在的必要了,根据这棵树就能遍历所有子对象,并将其释放掉

(当然并不是在这里,这里仅包含的是Frame对象的树结构)主要是用于界面显示布局层次和消息传递响应。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Composite——设计模式学习笔记 的相关文章

  • 设计模式之享元模式

    享元模式 就是共享技术 对于系统中存在大量相同的对象 把他们抽取成一个对象放在缓存中进行使用 这样可以大大节省系统资源 例如 围棋棋盘上有两种棋子 一个是黑子 一个是白子 如果在下棋的时候每下一个棋子就要new一个棋子对象 那么就会有大量的
  • Tomcat 系统架构与设计模式之工作原理篇

    本文以 Tomcat 5 为基础 也兼顾最新的 Tomcat 6 和 Tomcat 4 Tomcat 的基本设计思路和架构是具有一定连续性的 Tomcat 总体结构 Tomcat 的结构很复杂 但是 Tomcat 也非常的模块化 找到了 T
  • [设计模式]模板方法模式(Template Method)

    1 意图 定义一个操作中的算法的骨架 而将一些步骤延迟到子类中 TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 2 动机 其实就是如意图所描述的 算法的骨架是一样的 就是有些特殊步骤不一样 就可以
  • 程序员必知的23种设计模式之组合模式

    文章目录 1 模式引出 学校院系展示需求 1 1 传统方案 1 2 传统方案问题分析 2 组合模式基本介绍 2 1 方案修改 3 组合模式解决的问题 4 组合模式的注意事项和细节 1 模式引出 学校院系展示需求 编写程序展示一个学校院系结构
  • 设计模式之访问者模式

    访问者模式 把被操作的对象作为元素 可变可拓展的操作作为访问者 可以说访问者中有很多操作 然后访问者访问元素 对该元素进行操作 不同的访问者有不同的操作 案例 定义访问者接口 public interface UniversalVisito
  • DDD专家张逸:构建领域驱动设计知识体系

    张逸 读完需要 5分钟 速读仅需 2 分钟 领域驱动设计专家 曾就职于 ThoughtWorks 作为 Lead Consultant 为客户提供架构设计 大数据分析 持续交付 代码质量 敏捷管理等咨询服务 著译作包括 软件设计精要与模式
  • 组合型模式

    概述 对于这个图片肯定会非常熟悉 上图我们可以看做是一个文件系统 对于这样的结构我们称之为树形结构 在树形结构中可以通过调用某个方法来遍历整个树 当我们找到某个叶子节点后 就可以对叶子节点进行相关的操作 可以将这颗树理解成一个大的容器 容器
  • 【设计模式】工厂模式(Factory Pattern)

    1 概述 工厂模式 Factory Pattern 是最常用的设计模式之一 它属于创建类型的设计模式 它提供了一种创建对象的最佳方式 在工厂模式中 我们在创建对象时不会对客户端暴露创建逻辑 并且是通过一个共同的接口来指向新创建的对象 工厂模
  • 一个互联网研发团队的标准配置

    做一件大事 通常会产生一个组织 对于一个组织来说 确定了梦想和目标之后 首要的事情是 组织分工和明确 权责 权利和责任分不清楚 效率必定低下 读书阶段的时候 无论是学习 还是做事 从来没有深刻地感受过 事倍功半 和 事半功倍 工作之后 经历
  • 二十四种设计模式之策略模式

    一 什么是策略模式 简单来说 策略模式是将每一个算法封装到拥有共同接口的不同类中 使得算法可以在不影响客户端的情况下发生变化 也可以理解为可供程序运行时选择的 不同的类 不同的解决方案 策略模式的特点 高内聚低耦合 可扩展 遵循ocp原则
  • 「盘点」界面控件DevExtreme UI v23.1中的API增强

    DevExtreme gt https www evget com product 3150 拥有高性能的HTML5 JavaScript小部件集合 使您可以利用现代Web开发堆栈 包括React Angular ASP NET Core
  • 泛型与反射机制在JDBC和Servlet编程中的实践

    写在前面 泛型与反射是java中的两种强大机制 可以很好的提高代码的灵活性和复用性 本篇文章向大家展现在JDBC和Servlet编程场景下反射和泛型技术的实践 通过灵活使用这两种机制打造 高度可复用的JDBC和Servlet代码 1 JDB
  • 【QView】基于QML的UI组件框架 之 AImage (图片)

    先上结果演示 环境 不说版本就是耍流氓 硬件 通用PC 手机 Jetson Xavier NX 套件 均测试有效 系统 Ubuntu 20 04 Android Windows 均测试有效 软件 基于QT6 2 4 Qml 功能描述 AIm
  • 296_C++_一个dialog对话框在执行exec向系统发送一个延后销毁事件时,另一个对话框立刻接管了上一个对话框的销毁事件,导致死UI

    1 根因分析 根因分析 当有新版本并且grade等级是2的时候 点击ptz的时候使用的是RSDialog WA DeleteOnClose属性默认是为true的 并且是栈上的变量 当关闭ptz的时候 diolog的exec结束会向系统发送延
  • 设计模式—迭代器模式解析

    本文参考学习了 图解设计模式 中的代码实现和原理解释 迭代器模式 简介 Iterator 模式用于在数据集合中按照顺序遍历集合 就类似于我们的循环 一个个去遍历一个集合中的所有元素 示例代码 首先我们思考一个书本和书架的关系 显然 书架可以
  • Axure RP 8 for Mac/win中文版:打造完美交互式原型设计体验

    Axure RP 8 一款引领潮流的交互式原型设计工具 为设计师提供了无限的可能性 让他们能够创造出逼真的原型 从而更好地展示和测试他们的设计 Axure RP 8拥有丰富的功能和工具 让设计师可以轻松地创建出复杂的交互式原型 从简单的按钮
  • C++设计模式 #3策略模式(Strategy Method)

    动机 在软件构建过程中 某些对象使用的的算法可能多种多样 经常改变 如果将这些算法都写在类中 会使得类变得异常复杂 而且有时候支持不频繁使用的算法也是性能负担 如何在运行时根据需求透明地更改对象的算法 将算法和对象本身解耦 从而避免上述问题
  • element ui backTop源码解析-逐行逐析

    backTop 回到顶部 组件简介 基础概念 返回页面顶部的操作按钮 代码
  • 【设计模式之美】面向对象分析方法论与实现(二):需求到接口实现的方法论

    文章目录 一 进行面向对象设计 1 划分职责 gt 需要有哪些类 2 定义类及其属性和方法 3 定义类与类之间的交互关系 4 将类组装起来并提供执行入口 二 如何进行面向对象编程 1 接口实现
  • 一文从0到1手把手教学UI自动化测试之数据驱动!

    在UI的自动化测试中 我们需要把测试使用到的数据分离到文件中 如果单纯的写在我们的测试模块里面 不是一个好的设计 所以不管是什么类型的自动化测试 都是需要把数据分离出来的 当然分离到具体的文件里面 文件的形式其实有很多的 这里主要说明JSO

随机推荐

  • 机器学习苹果识别——python+opencv实现物体特征提取

    以水果为例 要用机器学习来实现水果识别 无论是训练还是识别阶段都需要提取图片中水果的特征值 本篇将讲述如何提取水果的周长 面积 颜色 长度 宽度7个特征值 cv findContours cv findContours将图片中识别到的轮廓返
  • 如何用matlab去修改图像尺寸

    img imread test1 jpg 这里为原始图像 i imresize img 567 390 imwrite i 1 jpg 这里为修改后图像 imread imresize和imwrite 1 imread 读取图像信息 A i
  • 查看VSCode版本

    背景 想要查看一下visual studio code的版本 方法 在vscode菜单栏 帮助 gt 发行说明 Help gt Release Notes 版本为1 36
  • C++auto_ptr的用法

    文章目录 一 auto ptr是什么 二 auto ptr需要包含的头文件 三 auto ptr用法 一 auto ptr是什么 auto ptr 是C 标准库提供的类模板 auto ptr对象通过初始化指向由new创建的动态内存 它是这块
  • TCP 协议(四)重传与超时

    1 TCP 协议中的计时器 TCP 中有四种计时器 Timer 分别为 重传计时器 Retransmission Timer 持久计时器 Persistent Timer 保活计时器 Keeplive Timer 等待计时器 Timer W
  • gdb+gdbserver远程调试技术

    首先声明 此文是在别人的基础上添加一些自己的体会 之前做嵌入式开发的时候 弄过一段时间gdb gdbserver远程调试 最后无果而终 只好将就用printf 首先感谢这篇刘品的文章 看着整洁清楚 http www cnblogs com
  • 目标检测之YOLOv3算法分析

    基本原理 特征网络 输入输出 输入 416 416 3 416 416 3 416 416 3大小的图片 不唯一 但图片大小必为32的倍数 输出3个尺度的feature map 分别为
  • 虹科分享

    说到应用程序和软件 关键词是 更多 在数字经济需求的推动下 从简化业务运营到创造创新的新收入机会 企业越来越依赖应用程序 云本地应用程序开发更是火上浇油 然而 情况是双向的 这些应用程序通常更复杂 使用的开放源代码比以往任何时候都包含更多的
  • 在Linux中使用线程

    我并不假定你会使用Linux的线程 所以在这里就简单的介绍一下 如果你之前有过多线程方面的编程经验 完全可以忽略本文的内容 因为它非常的初级 首先说明一下 在Linux编写多线程程序需要包含头文件pthread h 也就是说你在任何采用多线
  • printf()和cout的区别

    printf 和cout的区别 printf is a function that takes a variable number of arguments the first argument being a format string
  • Ubuntu使用内网穿透实现外网ssh远程登录

    Ubuntu使用内网穿透实现外网ssh远程登录 想要远程Ubuntu可以使用ssh网络协议进行远程登录 那什么时ssh呢 SSH 为 Secure Shell的缩写 由 IETF 的网络小组 Network Working Group 所制
  • Windows-tomcat 部署Java项目

    windows 通过 tomcat 部署项目 部署环境准备 JDK下载安装及配置 进入 Oracle官网 的 Java 界面 Oracle官网地址 https www oracle com java 1 JDK下载 1 1 在网站页面滚动鼠
  • 入门神经网络——浅层神经网络

    文章目录 一 基础知识 1 浅层神经网络介绍 2 浅层神经网络的正向传播 3 反向传播 二 浅层神经网络代码实例 一 基础知识 1 浅层神经网络介绍 此次构件浅层神经网络 相比于单神经元 浅层神经网络拥有多个神经元 因此又可以称为多神经元网
  • 网安等保

    欢迎关注 全栈工程师修炼指南 公众号 点击 下方卡片 即可关注我哟 设为 星标 每天带你 基础入门 到 进阶实践 再到 放弃学习 花开堪折直须折 莫待无花空折枝 作者主页 https www weiyigeek top 博客 https b
  • xshell连接Linux一直失败解决方法

    文章目录 解决对象 方法 配置 防火墙 关闭Linux防火墙 关闭Windows防火墙 xshell连接Linux一直失败解决方法 解决对象 可能出现以下两个问题 Linux防火墙已关闭和Windows防火墙已经关闭 配置好 vim etc
  • 分布式场景下基于拍卖算法的边缘智能节点任务分配

    摘 要 针对分布式场景下的边缘智能节点任务分配问题 构建了多类型的任务分配模型用于描述边缘智能节点与任务之间的关系 提出了一种基于拍卖算法的任务分配方法 智能边缘节点以动态拍卖的方式获取各自任务 基于拍卖算法的任务分配 智能边缘节点分为拍卖
  • iPad断触问题,iPencil正常,手指断触11个简便解决方法

    最开始上网搜 发现很多人都要此类情况 然后有人说是贴膜 带壳 人体导致的静电 有人说是iPad产品缺陷 有人说是接触不良 这里提供几个简便方法 有人换了三口插头 mac的充电线 链接地线可以放电 可以起到一定作用 简便方法1 一手摸pad屏
  • vue3中script setup获取动态组件component的Dom

    使用
  • MyBatis经典面试题及答案

    1 什么是MyBatis 答 MyBatis是一个可以自定义SQL 存储过程和高级映射的持久层框架 2 讲下MyBatis的缓存 答 MyBatis的缓存分为一级缓存和二级缓存 一级缓存放在session里面 默认就有 二级缓存放在它的命名
  • Composite——设计模式学习笔记

    Composite模式 一 意图 将对象组合成树形结构以表示 部分 整体 的层次结构 Composite使得用户对单个对象操作和组合对象的操作使用具有一致性 二 动机 绘图编辑器和图形捕捉系统图形应用程序中 总是存在简单的图形到简单的组件再