9、组合模式(结构性模式)

        组合模式又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构,以一致的方式处理叶子对象以及组合对象,不以层次高低定义类,都是结点类

       一、传统组合模式

        举例,大学、学院、系,它们之间不是继承关系,是组合关系:大学由学院组成,学院由系组成,但是它们都是组织结点,一个大学,n个学院,一个学院m个系,大学、学院是 组合类型的,它们都包含结点成员,系是 叶子类型 的,不包含结点成员

        把大学类、学院类、系类抽象为组织结点类,它们都是组织结点类的子类(其中大学子类、学院子类是组合类型的类,系是叶子类型的类),按照具体依赖抽象原则,以子类共有的属性和行为来定义结点类,代码如下:

//组织结点(基类)Organization
class Organization{                      //具体依赖抽象原则std::string name;//数据成员
public:Organization( std::string name):name(name) { }//构造函数virtual ~Organization(){ }                    //虚析构//其他成员函数virtual std::string getName(){ return name; }   virtual void add(Organization* o){ throw "叶子结点没有成员!\n"; }//virtual void remove( ){ throw "叶子结点没有成员!\n";  }virtual void print() = 0;  //
};    

        组合类型的子类University、College,重写基类成员函数,代码几乎一样

//组合类型(子类)University College
//University
class University:public Organization{std::list<Organization*> ul; //以基类的形式包含其他子类对象
public:University(std::string name):Organization(name) { }~University(){std:: cout << "~University\n";for(auto o:ul){ delete o; }		}//重写virtual void add(Organization* o){ul.push_back(o);}virtual void print(){std::cout << getName() << "\n";//基类成员获取,基类的成员也是子类的组成部分for( auto o:ul ){o->print();}}	
};//College
class College:public Organization{std::list<Organization*> cl; //以基类的形式包含其他子类对象
public:College(std::string name):Organization(name) { }~College(){std:: cout << "~College\n";for(auto o:cl){ delete o; }		}//重写virtual void add(Organization* o){cl.push_back(o);}virtual void print(){std::cout << getName() << "\n";//基类成员获取,基类的成员也是子类的组成部分for( auto o:cl ){o->print();}}	
};

        叶子类型的子类(Department)

//叶子类型(子类)Department
class Department:public Organization{
public:Department(std::string name):Organization(name) { }~Department(){std:: cout << "~Department\n";}//重写virtual void print(){std::cout << getName() << "\n";}
};

        头文件及测试代码

#include <iostream>
#include <string>
#include <exception>
#include <list>int main() 
{University u("清华大学");Organization* c1 = new College("计算机学院");Organization* c2 = new College("信息工程学院");Organization* d = new Department("信息工程");u.add( c1 );u.add( c2 );c2->add( d );u.print();//c2->print();	return 0;
}

        二、组合模式的结点设计

        把组合类型的的属性、行为都放到结点,以对象组是否为空来判断是叶子类型的还是组合类型的,这样叶子类型也可以扩展为组合类型,虽然看起来有点混乱,但是确实可行,比如系原来是叶子,现在有了个学生会,添加成员后就可以不是叶子了

#include <iostream>
#include <string>
#include <exception>
#include <list>//组织结点(基类)Organization
class Organization{  //具体依赖抽象原则std::string name;//数据成员std::list<Organization*> ol; //对象组
public:Organization( std::string name):name(name) { } //构造函数virtual ~Organization(){	 //虚析构for(auto o:ol){ delete o; }	}                    //其他成员函数 virtual void add(Organization* o){ ol.push_back(o); }	virtual void print(){std::cout << name << "\n";if( !ol.empty() ) //判断是否是叶子结点{ for( auto o:ol ){o->print();}}	}
};    //University
class University:public Organization{
public:University(std::string name):Organization(name) { }~University(){ std:: cout << "~University\n"; }
};//College
class College:public Organization{std::list<Organization*> cl; //以基类的形式包含其他子类对象
public:College(std::string name):Organization(name) { }~College(){std:: cout << "~College\n";}
};//Department
class Department:public Organization{
public:Department(std::string name):Organization(name) { }~Department(){std:: cout << "~Department\n";}
};//StudentUnion
class StudentUnion:public Organization{
public:StudentUnion(std::string name):Organization(name) { }~StudentUnion(){std:: cout << "~StudentUnion\n";}
};int main() 
{University u("清华大学");Organization* c1 = new College("计算机学院");Organization* c2 = new College("信息工程学院");Organization* d1 = new Department("信息工程");Organization* d2 = new Department("软件工程");Organization* s = new StudentUnion("信息工程学生会");d1->add( s );c1->add( d2 );c2->add( d1 );u.add( c1 );u.add( c2 );u.print( );//c2->print( );	return 0;
}

        三、修改打印函数,打印出树形结构

         1、 修改print

    virtual void print( int depth ){for(int i=0; i< depth; ++i)std:: cout << "--";std::cout << name << "\n";if( !ol.empty() ) //判断是否是叶子结点{ for( auto o:ol ){o->print(depth+1);}}	}

        2、调用修改为

u.print(0);
//c2->print( 0 );

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

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

相关文章

优秀的前端框架vue,原理剖析与实战技巧总结【干货满满】

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属的专栏&#xff1a;前端零基础教学&#xff0c;实战进阶 景天的主页&#xff1a;景天科技苑 文章目录 Vuevue.js库的基本使用vue.js的M-V-VM思…

flutter入门

本文真对 Flutter 的技术特性&#xff0c;做了一些略全面的入门级的介绍&#xff0c;如果你听说过Flutter&#xff0c;想去了解它&#xff0c;但是又不想去翻厚厚的API&#xff0c;那么本文就是为你准备的。 随着纯客户端到Hybrid技术&#xff0c;到RN&Weex&#xff0c;再…

24计算机考研调剂 | 东北石油大学

东北石油大学智能物探团队招生宣传 考研调剂招生信息 学校:东北石油大学 专业:工学->地质资源与地质工程->矿产普查与勘探 年级:2024 招生人数:2 招生状态:正在招生中 联系方式:********* (为保护个人隐私,联系方式仅限APP查看) 补充内容 团队介绍&#xff1a; …

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的血细胞智能检测与计数(深度学习模型+UI界面代码+训练数据集)

摘要&#xff1a;开发血细胞智能检测与计数系统对于疾病的预防、诊断和治疗具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个血细胞智能检测与计数系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&a…

C++顺序结构实例

1.计算浮点数相除的余数 计算两个双精度浮点数a和b相除的余数,a和b都是双精度浮点数。这里的余数r的定义是: a=k * 吧+r,其中k是整数,0<=r<b。 输入 一行,包括两个双精度浮点数a和b 输出 一行,a➗b的余数 样例输入 73.263 0.9973 样例输出 0.4301 #i…

jdk17下载安装图文教程【超详细】

目录 一、下载JDK17 二、安装JDK17 三、配置环境变量 四、测试Java安装是否成功 一、下载JDK17 访问官网&#xff1a;Java Downloads | Oracle 二、安装JDK17 三、配置环境变量 右键点击我的电脑>属性>高级系统设置>环境变量 在【系统变量】中新建JAVA_HOME&…

ROS2 launch rs_launch.py的说明(设置分辨率、配准、pcl图等)

ROS2 launch rs_launch.py的说明&#xff08;设置分辨率、配准、pcl图等&#xff09; 文章目录 前言正文下载安装方式参数示例指令 前言 本文目的是记录下当前ROS2版本apt install 的 realsense-ros的rs_launch文件中参数有哪些及如何配置。 正文 下载安装方式 # 使用apt i…

记录西门子:SCL设置不同顺序

一台搅拌的设备&#xff0c;需要控制三种料的进料顺序和进料重量&#xff0c;顺序和重量可以随便设定&#xff0c;也可以是几十种料。触摸屏上面有A、B、C三种液体原料&#xff0c;需要设定三种液体原料重量&#xff0c;并设定序号。 假设如下面所示设定&#xff1a;那将先打开…

C#面:System.Array.CopyTo() 和 System.Array.Clon() 的区别

二者都是用于复制数组的方法&#xff0c;但它们有一些区别&#xff1a; System.Array.CopyTo()&#xff1a; 方法签名&#xff1a;void CopyTo(Array array, int index)功能&#xff1a;将当前数组的所有元素复制到另一个数组中。参数&#xff1a; array&#xff1a;目标数组…

AI 技术:改变世界的力量

人工智能&#xff08;AI&#xff09;是当今科技领域最热门的话题之一&#xff0c;它已经成为推动社会进步和经济发展的重要力量。AI 技术的应用范围非常广泛&#xff0c;从智能手机、自动驾驶汽车到医疗保健、金融服务等领域&#xff0c;都可以看到 AI 的身影。 那么&#xff0…

4. 数据库建库建表规范和原理,白话版

文章目录 数据库建库建表规范和原理&#xff0c;白话版1. 数据库的字符集&#xff1a;为何utf8成为首选&#xff1f;2. 为什么要注意数据库的排序规则&#xff1f;3. 怎么建表名&#xff1f;4. 为什么表中会创建id和code&#xff1f;5. 主键id的命名规则6. 关联键的命名规则7. …

【考研数学】打基础用张宇《30讲》还是武忠祥《基础篇》?

基础课不太可能所有的东西全都覆盖&#xff0c;还是先搭起一个知识框架&#xff0c;然后不断的填充和完善。 所以不必太过于在意少一些东西&#xff0c;我们不可能一口吃成胖子&#xff0c;基础知识肯定不会遗漏的&#xff0c;只可能一些技巧不到位。 从自己的情况考虑&#…

【哈希表算法题记录】15. 三数之和,18. 四数之和——双指针法

题目链接 15. 三数之和 思路 这题虽然放在哈希表的分类里面&#xff0c;但是用双指针法会更高效。 之前的双指针我们要么是一头left一尾right&#xff0c;要么是快fast慢slow指针。这里是要计算三个数的和&#xff0c;我们首先对数组进行从小到大的排序&#xff0c;先固定一…

./gradlew assembleRelease

在 Android 项目中使用 Gradle 进行打包&#xff0c;通常会涉及到配置 build.gradle 文件。其中&#xff0c;你需要指明签名配置&#xff08;signing config&#xff09;和构建类型&#xff08;build type&#xff09;。以下是一个基本的配置示例&#xff1a; 首先&#xff0c…

Docker 进阶

1、容器数据卷 什么是容器数据卷&#xff1f; 就是当容器内存在了mysql&#xff0c;在里面书写了数据&#xff0c;如果容器删除了&#xff0c;那么数据也就没有了&#xff0c;通过容器数据卷的技术&#xff0c;可以让容器内的数据持久化到Linux服务器上 操作 #docker run -…

三、HarmonyOS 应用开发入门之运行Hello World

目录 1、课程对象 1.1、有移动端开发经验 1.2、无移动端开发经验 1.3、对 HarmonyOS 感兴趣 2、DevEco Studio 的使用 2.1、DevEco Studio 的关键特性 智能代码编辑 低代码开发 多段双向实时预览 多端模拟仿真 2.2、安装配置 DevEco Studio 2.2.1、官网开发工具下载地…

基于Springboot的面向智慧教育的实习实践系统设计与实现(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的面向智慧教育的实习实践系统设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&…

_数据_变量_内存

什么是数据? 存储于内存中代表特定信息的’东东’, 本质就是0101二进制具有可读和可传递的基本特性万物(一切)皆数据, 函数也是数据程序中所有操作的目标: 数据 算术运算逻辑运算赋值调用函数传参 … 什么是内存? 内存条通电后产生的存储空间(临时的)产生和死亡: 内存条(…

《深入Linux内核架构》第2章 进程管理和调度 (1)

目录 前言 2.1 进程优先级 2.2 进程生命周期 2.3 进程表示 2.3.1 进程类型 2.3.2 命名空间 2.3.3 进程ID号 2.3.4 进程关系 2.4 进程管理相关的系统调用 2.4.1 进程复制 2.4.2 内核线程 2.4.3 启动新程序 2.4.4 退出进程 前言 本章内容太多&#xff0c;分为两篇博…