设计模式9、组合模式 Composite

news2024/11/17 19:37:58
解释说明:组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。
抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性
树枝节点(Composite):定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点行程一个树形结构
叶子节点(Left):叶子节点对象,其下再无分支,是系统层次遍历的最小单位
优点:
    可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让 Client 忽略了层次的差异,方便对整个层次结构进行控制。
    Client 可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了 Client 的代码。
    在组合模式中,增加新的叶子构件和容器构件很方便,无须对现有类进行任何修改,符合“开闭原则”。
    为树形结构提供了一种灵活的解决方案,通过递归组合容器对象和叶子对象,可以形成复杂的树形结构,但对树形结构的控制却非常简单。
缺点:
    使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式具有很大挑战性,而且不是所有的方法都与叶子对象子类都有关联。
适用场景
    表示对象的“整体-部分”层次结构(树形结构)
    希望用户忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象
#pragma once
#include <iostream>
#include <string>
/****组合模式 Composite******/
using namespace std;
class Component
{
public:
       Component(string name) : m_strName(name) {}
       virtual ~Component() {}
       virtual void Add(Component* cmpt) = 0;  // 添加构件
       virtual void Remove(Component* cmpt) = 0;  // 删除构件
       virtual Component* GetChild(int index) = 0;  // 获取构件
       virtual void Operation(int indent) = 0;  // 显示构件(以缩进的方式)
private:
       Component();  // 不允许
protected:
       string m_strName;
};

#pragma once
#include <vector>
#include "component.h"
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} }
#endif
class Composite : public Component
{
public:
       Composite(string name) : Component(name) {}
       virtual ~Composite() {
              while (!m_elements.empty()) {
                     vector<Component*>::iterator it = m_elements.begin();
                     SAFE_DELETE(*it);
                     m_elements.erase(it);
              }
       }
       void Add(Component* cmpt) {
              m_elements.push_back(cmpt);
       }
       void Remove(Component* cmpt) {
              vector<Component*>::iterator it = m_elements.begin();
              while (it != m_elements.end()) {
                     if (*it == cmpt) {
                           SAFE_DELETE(cmpt);
                           m_elements.erase(it);
                           break;
                     }
                     ++it;
              }
       }
       Component* GetChild(int index) {
              if (index >= m_elements.size())
                     return NULL;
              return m_elements[index];
       }
       // 递归显示
       void Operation(int indent) {
              string newStr(indent, '-');
              cout << newStr << "+ " << m_strName << endl;
              // 显示每个节点的孩子
              vector<Component*>::iterator it = m_elements.begin();
              while (it != m_elements.end()) {
                     (*it)->Operation(indent + 2);
                     ++it;
              }
       }
private:
       Composite();  // 不允许
private:
       vector<Component*> m_elements;
};

#pragma once
#include "component.h"
class Leaf : public Component
{
public:
       Leaf(string name) : Component(name) {}
       virtual ~Leaf() {}
       void Add(Component* cmpt) {
              cout << "Can't add to a Leaf" << endl;
       }
       void Remove(Component* cmpt) {
              cout << "Can't remove from a Leaf" << endl;
       }
       Component* GetChild(int index) {
              cout << "Can't get child from a Leaf" << endl;
              return NULL;
       }
       void Operation(int indent) {
              string newStr(indent, '-');
              cout << newStr << " " << m_strName << endl;
       }
private:
       Leaf();  // 不允许
};

#include "composite.h"
#include "leaf.h"
int main()
{
       // 创建一个树形结构
       // 创建根节点
       Component* pRoot = new Composite("江湖公司(任我行)");
       // 创建分支
       Component* pDepart1 = new Composite("日月神教(东方不败)");
       pDepart1->Add(new Leaf("光明左使(向问天)"));
       pDepart1->Add(new Leaf("光明右使(曲洋)"));
       pRoot->Add(pDepart1);
       Component* pDepart2 = new Composite("五岳剑派(左冷蝉)");
       pDepart2->Add(new Leaf("嵩山(左冷蝉)"));
       pDepart2->Add(new Leaf("衡山(莫大)"));
       pDepart2->Add(new Leaf("华山(岳不群)"));
       pDepart2->Add(new Leaf("泰山(天门道长)"));
       pDepart2->Add(new Leaf("恒山(定闲师太)"));
       pRoot->Add(pDepart2);
       // 添加和删除叶子
       pRoot->Add(new Leaf("少林(方证大师)"));
       pRoot->Add(new Leaf("武当(冲虚道长)"));
       Component* pLeaf = new Leaf("青城(余沧海)");
       pRoot->Add(pLeaf);
       // 小丑,直接裁掉
       pRoot->Remove(pLeaf);
       // 递归地显示组织架构
       pRoot->Operation(1);
       // 删除分配的内存
       SAFE_DELETE(pRoot);
       getchar();
       return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1060059.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

两种新建CAA项目快捷启动方式

文章目录 一、前言二、新建项目快捷启动方式&#xff08;相当于直接Cnext进入&#xff09;方式一&#xff1a;按下面图示操作&#xff08;以V5 R21为例&#xff09;方式二&#xff1a;按下面图示操作&#xff08;以V5 R18为例&#xff09; 一、前言 环境变量配置文件可存放路径…

字典与数组第七讲:工作表数据计算时为什么要采用数组公式(一)

《VBA数组与字典方案》教程&#xff08;10144533&#xff09;是我推出的第三套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;字典是VBA的精华&#xff0c;我要求学员必学。7.1.3.9教程和手册掌握后&#xff0c;可以解决大多数工作中遇到的实际问题。…

个人论坛系统的测试用例

首先要弄清楚论坛系统都具有什么功能&#xff0c;然后对各个功能进行分类编写测试用例。

使用Sen2cor对Sentinel-2辐射定标和大气校正

使用Sen2cor对Sentinel-2辐射定标和大气校正 在上一篇文章中&#xff0c;先对Sen2cor进行了安装 先定位到插件所在文件夹下 cd C:\Users\lenovo\AppData\Local\Sen2Cor-02.11.00-win64如果在上一篇中已经配置好环境变量&#xff0c;那就不用cd定位了&#xff0c;直接输后面的…

经典算法-----八皇后问题

目录 前言 八皇后问题 1.问题简介 1.2思路剖析 1.3递归和回溯 代码实现 ​编辑 1.递归回溯解决 能否放置数组 完整代码&#xff1a; 2.非递归回溯解决 前言 今天我们学习一个新的算法&#xff0c;也就是回溯算法&#xff0c;就以八皇后问题作为示例&#xff0c;这是…

剑指offer——JZ25 合并两个排序的链表 解题思路与具体代码【C++】

一、题目描述与要求 两个链表的第一个公共结点_牛客题霸_牛客网 (nowcoder.com) 题目描述 输入两个无环的单向链表&#xff0c;找出它们的第一个公共结点&#xff0c;如果没有公共节点则返回空。&#xff08;注意因为传入数据是链表&#xff0c;所以错误测试数据的提示是用其…

C++的对像生存期

栈 栈由操作系统分配管理&#xff0c;也就是它是规整的&#xff0c;内存的大小在申请之后不会发生变化。因此&#xff0c;它不会出现碎片化&#xff0c;并且读取速度非常的快 例如&#xff1a;经常声明的局部变量&#xff0c;一些基本数据类型&#xff0c;如int ,double, char…

力扣 -- 518. 零钱兑换 II(完全背包问题)

解题步骤&#xff1a; 参考代码&#xff1a; 未优化代码&#xff1a; class Solution { public:int change(int amount, vector<int>& coins) {int ncoins.size();//多开一行&#xff0c;多开一列vector<vector<int>> dp(n1,vector<int>(amount1…

LLVM IR 文档 专门解释 LLVM IR

https://llvm.org/docs/LangRef.html#phi-instruction

Linux网络编程:详解https协议

目录 一. https协议概述 二. 中间人截获 三. 常见的加密方法 3.1 对称加密 3.2 非对称加密 四. 数据摘要和数据签名的概念 五. https不同加密方式的安全性的探究 5.1 使用对称加密 5.2 使用非对称加密 5.3 非对称加密和对称加密配合使用 六. CA认证 七. 总结 一.…

JWFD开源工作流大模型设计器

JWFD开源工作流大模型设计器&#xff0c;把流程图的拓扑结构从几十个节点扩展到数千个节点&#xff0c;就不是使用绘图器的模式了&#xff0c;需要开发一个模型生成器了&#xff0c;尝试做一下大模型&#xff0c;赶赶时髦啊

openwrt安装与旁路由 以玩客云为例

鉴于安了wfnb/onecloud 23年的bata版本 结果发现进入docker 连make config apt yum apk curl等命令都没有……而且curl下载很慢 得选6.0哪个版本 反正就是 安不了istore 所以 直接刷人家的成品算了 为什么要使用软路由、旁路由 普通的路由器往往集无线信号转发、网关、DNS 服…

JMeter工具的介绍,安装

一、本文学习目标 1、能知道JMeter的优缺点 2、能掌握JMeter的安装流程 3、能掌握JMeter线程组的设置 4、能掌握JMeter参数化的使用 5、能掌握JMeter直连数据库操作 6、能掌握JMeter的断言. 二、JMeter简介 &#xff08;1&#xff09;Jmeter详细介绍 **JMeter&#xff08;A…

RTC 时间、闹钟

实时时钟RTC是一个独立的定时器。RTC模块拥有一个连续计数的计数器&#xff0c;在软件配置下&#xff0c;可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期 RTC还包含用于管理低功耗模式的自动唤醒单元。 在掉电情况下 RTC仍可以独立运行 只要芯片的备用电源…

MySQL数据库基础回顾与复习

MySQL数据库 一、原理定义概念 定义 数据库(Database)是按照数据结构来组织、存储和管理数据的建立在计算机存储设备上的仓库 数据库是长期储存在计算机内、有组织的、可共享的数据集合 分类&#xff1a; &#xff08;1&#xff09;非结构化数据&#xff1a; 数据相对来讲没…

QFluentWidgets: 基于 C++ Qt 的 Fluent Design 组件库

简介 QFluentWidgets 是一个基于 Qt 的 Fluent Designer 组件库&#xff0c;内置超过 150 个开箱即用的 Fluent Designer 组件&#xff0c;支持亮暗主题无缝切换和自定义主题色。搭配所见即所得的 Fluent Designer 软件&#xff0c;只需拖拖拽拽&#xff0c;不用编写一行 QSS&…

腾讯云服务器简介和使用流程

腾讯云服务器在云服务器CVM或轻量应用服务器页面自定义购买价格比较贵&#xff0c;但是自定义购买云服务器CPU内存带宽配置选择范围广&#xff0c;活动上购买只能选择固定的活动机&#xff0c;选择范围窄&#xff0c;但是云服务器价格便宜比较省钱。腾讯云服务器网来详细说下腾…

driver.js 扩展下次“不再提示”功能

文档地址&#xff1a;https://github.com/kamranahmedse/driver.js 官方demo&#xff1a;https://kamranahmed.info/driver.js/ /*** Title: 页面引导 ……* Author: JackieZheng* Date: 2023-08-16 10:43:31* LastEditTime: 2023-08-16 10:55:08* LastEditors:* Description:*…

找不到msvcp110.dll是什么意思?总结msvcp110.dll丢失修复方法分享

随着电脑技术的不断发展&#xff0c;我们也会遇到各种各样的问题。最近&#xff0c;我就遇到了一个问题&#xff1a;电脑丢失msvcp110.dll的困扰。这个问题让我深感无奈&#xff0c;但同时也让我学到了很多关于电脑维修和系统修复的知识。在这篇文章中&#xff0c;我将分享我的…

前端JavaScript入门到精通,javascript核心进阶ES6语法、API、js高级等基础知识和实战 —— Web APIs(五)

思维导图 Bom操作 一、Window对象 1.1 BOM(浏览器对象模型) <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"vi…