设计模式 --6组合模式

文章目录

    • 组合模式应用场景
    • 组合模式概念
    • 组合模式结构图
    • 透明方式和安全方式
    • 什么时候使用组合模式
    • 公司管理系统使用 组合模式来构架
    • 组合模式的好处

组合模式应用场景

整体和部分可以被一致性对待 比如人力资源部 财务部的管理功能可以复用于分公司的功能
可以引入一种 树状的结构 来统一管理

组合模式概念

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

组合模式结构图

在这里插入图片描述


#include <iostream>
#include <list>
using namespace std;

//组合中对象声明接口 实现所有类共有的默认接口行为
class Component {
public:
	Component(string name)
	{
		this->name = name;
	}
	virtual void Add(Component *c) {};
	virtual void Remove(Component* c) {};
	virtual void Display(int depth) {};//展示参数表示数的深度


protected:
	string name;
};


// 在组合里面表示叶子节点对象 叶节点没有子节点
class Leaf :public Component
{
public:
	Leaf(string name) :Component(name) {

	}
	void Add(Component* c) override {
		cout << "cannot add to a leaf " << endl;
	}

	void Remove(Component* c) override {
		cout << "cannot Remove from  a leaf " << endl;
	}

	void Display(int depth) override {
		string a = string(depth, '-');
		cout << a << name << endl;
	}

};

//在组合里面定义有子节点行为 用来存储子部件
class Composite : public Component
{
public:
	Composite(string name) :Component(name) {

	}
	void Add(Component *c) override {
		children.push_back(c);
	}
	void Remove(Component *c) override {
		children.remove(c);
	}

	void Display(int depth)override
	{
		cout << string(depth, '-') << name << endl;

		for (auto Com : children)
		{
			Com->Display(depth + 2);
		}
	}



private:
	list<Component*> children;
};

int main()
{
	Composite * root = new Composite("root");
	root->Add(new Leaf("Leaf A"));
	root->Add(new Leaf("Leaf B"));

	Composite* comp = new Composite("Composite X");
	comp->Add(new Leaf("Leaf XA"));
	comp->Add(new Leaf("Leaf XB"));

	root->Add(comp);

	Composite *comp2 = new Composite("Composite XY");
	comp2->Add(new Leaf("Leaf XYA"));
	comp2->Add(new Leaf("Leaf XYB"));

	comp->Add(comp2);

	root->Add(new Leaf("Leaf C"));
	Leaf * leaf = new Leaf("Leaf D");
	root->Add(leaf);
	root->Remove(leaf);
	root->Display(1);

	return 0;
}

代码运行结果能显示出 树状的组件
在这里插入图片描述

透明方式和安全方式

透明方式
在这种实现里面 Component 中声明了所有用来管理子对象的方法 对于外界来说 叶子节点和子节点没有区别 它们具有完全一样的接口 Leaf 本身不具备Add Remove方法 所以实现它是没有任何意义的
安全方式
在Component里面不去声明Add 和 Remove方法 这样子类Left不需要去实现,而是在Composite声明所有用来管理子类对象的方法 这样做就不会遇到刚才遇到的问题 但是由于不够透明 所以树枝类将不具有相同的接口 客户端的调用需要做判断

应该视情况 来决定使用哪一种方式

什么时候使用组合模式

需求中体现部分和整体层次的结构的时候 希望用户可以忽略组合对象和单个对象的不同,统一地使用组合结构中的所有对象时 ,就应该考虑使用组合模式了
TreeView 控件使用的就是组合模式

公司管理系统使用 组合模式来构架

在这里插入图片描述


#include <iostream>
#include <list>
using namespace std;

//组合中对象声明接口 实现所有类共有的默认接口行为
class Company {
public:
	Company(string name)
	{
		this->name = name;
	}
	virtual void Add(Company *c) = 0;
	virtual void Remove(Company* c) = 0;
	virtual void Display(int depth) =0 ;//展示参数表示数的深度
	virtual void LineOfDuty() =0; //履行职责


protected:
	string name;
};


// 人力资源部门
class HRDepartment :public Company
{
public:
	HRDepartment(string name) :Company(name) {

	}
	void Add(Company* c) override {
		cout << "cannot add to a leaf " << endl;
	}

	void Remove(Company* c) override {
		cout << "cannot Remove from  a leaf " << endl;
	}

	void Display(int depth) override {
		string a = string(depth, '-');
		cout << a << name << endl;
	}
	void LineOfDuty()override
	{
		cout << name<<" 员工招聘培训管理 " << endl;
	}

};

//具体公司类 实现接口 树枝节点
class ConcreteCompany : public Company
{
public:
	ConcreteCompany(string name) :Company(name) {

	}
	void Add(Company *c) override {
		children.push_back(c);
	}
	void Remove(Company *c) override {
		children.remove(c);
	}

	void Display(int depth)override
	{
		cout << string(depth, '-') << name << endl;

		for (auto Com : children)
		{
			Com->Display(depth + 2);
		}
	}
	//履行职责
	void LineOfDuty() override {
		for (auto Com : children)
		{
			Com->LineOfDuty();
		}
	}


private:
	list<Company*> children;
};

//财务部
class FinanceDepartment :public Company
{
public:
	FinanceDepartment(string name) :Company(name) {

	}
	void Add(Company* c) override {
		cout << "cannot add to a leaf " << endl;
	}

	void Remove(Company* c) override {
		cout << "cannot Remove from  a leaf " << endl;
	}

	void Display(int depth) override {
		string a = string(depth, '-');
		cout << a << name << endl;
	}
	void LineOfDuty()override
	{
		cout << name << " 公司财务收支管理 " << endl;
	}

};

int main()
{
	ConcreteCompany * root = new ConcreteCompany("北京总公司");
	root->Add(new HRDepartment("总公司人力资源"));
	root->Add(new HRDepartment("总公司财务部门"));

	ConcreteCompany* comp = new ConcreteCompany("上海华东分公司");
	comp->Add(new HRDepartment("华东分公司人力资源部"));
	comp->Add(new HRDepartment("华东分公司财务部"));

	root->Add(comp);

	ConcreteCompany *comp2 = new ConcreteCompany("南京办事处");
	comp2->Add(new HRDepartment("南京办事处人力资源部"));
	comp2->Add(new HRDepartment("南京办事处财务部"));
	comp->Add(comp2);

	ConcreteCompany* comp1 = new ConcreteCompany("杭州办事处");
	comp1->Add(new HRDepartment("杭州办事处人力资源部"));
	comp1->Add(new HRDepartment("杭州办事处财务部"));

	comp->Add(comp1);

	cout << "结构图 :" << endl;
	root->Display(1);
	cout << "职责:" << endl;
	root->LineOfDuty();

	return 0;
}

运行后的结果图
在这里插入图片描述

组合模式的好处

组合模式定义基本对象和分公司 办事处结合对象的类层次结构 基本对象可以被组合成更复杂的类型
组合对象又可以被组合 这样不断地柜下去 客户代码 任何用到基本对象的地方都可以使用组合对象

组合模式让客户可以一致的使用组合结构和单个对象

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【webrtc】MessageHandler 2: 基于线程的消息处理:以PeerConnectionClient为例

PeerConnectionClient 前一篇 nullaudiopoller 并么有场景线程,而是就是在当前线程直接执行的, PeerConnectionClient 作为一个独立的客户端,默认的是主线程。 PeerConnectionClient 同时维护客户端的信令状态,并且通过OnMessage实现MessageHandler 消息处理。 目前只处理一…

AI大模型日报#0430:疑似GPT4.5模型刷屏、上交实现「蛋白质功能定向进化」、微软紧急撤回WizardLM-2

导读&#xff1a; 欢迎阅读《AI大模型日报》&#xff0c;内容基于Python爬虫和LLM自动生成。目前采用“文心一言”生成了今日要点以及每条资讯的摘要。 《AI大模型日报》今日要点&#xff1a; 在AI大模型领域&#xff0c;多项研究进展和行业应用动态引发关注。一夜之间&#x…

Gateway Predicate断言(谓词)

是什么 Spring Cloud Gateway匹配路由作为Spring WebFlux HandlerMapping基础设施的一部分。 Spring Cloud Gateway包含许多内置的路由谓词工厂。 所有这些谓词都匹配HTTP请求的不同属性。 您可以使用逻辑 and 语句来联合收割机组合多个路由谓词工厂。 Predicate就是为了实现一…

sum函数搭配group by /having的案例说明

记录一些常用的函数及用法 --查询份额大于1w的投资人信息。 聚合数据的筛选&#xff1a;当你需要基于聚合函数&#xff08;如 SUM(), AVG(), MAX(), MIN(), COUNT() 等&#xff09;的结果来过滤记录时&#xff0c;使用 HAVING 子句。 组合条件&#xff1a;HAVING 子句可以使用…

Nginx配置Https缺少SSL模块

1、Linux下Nginx配置https nginx下载和安装此处就忽略&#xff0c;可自行百度 1.1、配置https 打开nginx配置文件 vim /opt/app/nginx/conf/nginx.conf相关https配置 server {listen 443 ssl; #开放端口server_name echarts.net;#域名#redirect to https#ssl on; #旧版#ssl证…

ubuntu 利用阿里网盘API实现文件的上传和下载

文章目录 背景脚本初始化 阿里云盘API工具 aligo安装aligoaligo教程实战parse.py 演示上传文件上传文件夹下载文件下载文件夹 背景 最近在用ubuntu系统做实验&#xff0c;而ubuntu 系统的文件上传和下载操作很麻烦&#xff1b; 于是便打算使用阿里网盘的API 进行文件下载与上传…

VitePress 构建的博客如何部署到 Netlify 平台?

VitePress 构建的博客如何部署到 Netlify 平台&#xff1f; 前言 之前写了篇文章【使用 Vitepress 构建博客并部署到 github 平台】&#xff0c;有个老哥说 github page 访问太慢了&#xff0c;希望放到 Netlify 平台上面。 咱也没部署过&#xff0c;就试了一下&#xff0c;发…

JAVA面试专题-Redis

你在最近的项目中哪些场景使用了Redis 缓存 缓存穿透 缓存穿透&#xff1a;查询一个不存在的数据&#xff0c;mysql查询不到数据也不好直接写入缓存&#xff0c;导致每次请求都查数据库。 解决方案一&#xff1a;缓存空数据&#xff0c;即使查询返回的数据为空&#xff0c;也把…

C#应用程序实现多屏显示

前言 随着业务发展&#xff0c;应用程序在一些特定场景下&#xff0c;只在一个显示器上展示信息已经不能满足用户需求。我们如何把主屏运行程序中多个窗体移动到各个扩展屏幕位置显示呢&#xff1f;C# 是通过什么方式来实现的&#xff0c;下面介绍 C# 使用 Screen 类的方式来实…

vue+elementUI实现点击左右箭头切换按钮功能

原本是可以用el-tabs做的,就像下面的样式,但是领导说不行 最后用button和element里面的el-carousel(走马灯)结合了一下 长这样 感觉还不错 可以自己改样式 代码如下: <div class"drawer-carousel"><el-carousel arrow"always" :loop"false…

Linux基础part-5

1、Linux用户与用户组管理 1、用户是什么&#xff1f; 实现资源分派&#xff08;区分和管理系统资源的访问权限&#xff0c;将不同的资源分配给不同的用户&#xff09;实现认证pam和授权&#xff08;用户身份通常通过用户名和密码进行认证&#xff0c;认证成功后系统将授予用…

开源、轻量、易用的服务器实时监控工具:哪吒探针

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 哪吒探针是一个开源、轻量、易用的服务器监控、运维工具&#xff0c;它有以下几个特点&#xff1a; 一键安装&#xff1a;可以一键安装面板与 Agent&#xff0c;并且支持 Linux、Windows、MacOS、OpenWRT…

scikit-learn:Python中的机器学习-1

简介&#xff1a;问题设置 什么是机器学习&#xff1f; 机器学习是关于构建具有可调参数的程序&#xff0c;这些参数可以自动调整&#xff0c;以便通过适应先前看到的数据来改善其行为。机器学习可以被认为是人工智能的一个子领域&#xff0c;因为这些算法可以被视为构建模块…

气象数据nc数据矢量化处理解析及可视化

气象数据可视化是将气象学领域中复杂的数据集转化为图形或图像的过程&#xff0c;以直观展示天气现象、气候模式、趋势和预报结果。气象数据的可视化技术广泛应用于科学研究、气象预报、航空、航海、农业生产、灾害预警系统、城市规划、公众服务等领域。以下是一些关键的气象数…

CSAPP | Bits, Bytes, and Integers

Great Reality Ints are not Integers, Floats are not Reals 对于 (x y) z x (y z)&#xff0c;无符号整形和有符号整形是成立的。 但是对于浮点数, (1e20 -1e20) 3.14 -> 3.14&#xff0c;而 1.e20 (-1e20 3.14) 0 typedef struct {int a[2];double d; }stru…

【LeetCode】拓扑排序——课程表 I II

拓扑排序&#xff1a; AOV网&#xff1a;若用DAG图&#xff08;有向无环图&#xff09;表示一个工程&#xff0c;其顶点表示活动&#xff0c;用有向边<Vi, Vj>表示活动Vi必须先于活动Vj进行的这样一种关系&#xff0c;则将这种有向图称为顶点表示活动的网络&#xff0c;…

JSP:操作指令

目录 目录 一、jsp:useBean操作 语法格式&#xff1a; 属性说明&#xff1a; scope作用域&#xff1a; 1.page&#xff1a; 2.request&#xff1a; 3.session&#xff1a; 4.application 案例&#xff1a;JavaBean的简单使用 二、jsp:setProperty操作 语法格式&a…

【记录】Python3| 将 PDF 转换成 HTML/XML(✅⭐⭐⭐⭐pdf2htmlEX)

本文将会被汇总至 【记录】Python3&#xff5c;2024年 PDF 转 XML 或 HTML 的第三方库的使用方式、测评过程以及对比结果&#xff08;汇总&#xff09;&#xff0c;更多其他工具请访问该文章查看。 文章目录 pdf2htmlEX 使用体验与评估1 安装指南2 测试代码3 测试结果3.1 转 HT…

jenkins转载文本

基于Docker容器DevOps应用方案 企业业务代码发布系统 一、企业业务代码发布方式 1.1 传统方式 以物理机或虚拟机为颗粒度部署部署环境比较复杂&#xff0c;需要有先进的自动化运维手段出现问题后重新部署成本大&#xff0c;一般采用集群方式部署部署后以静态方式展现 1.2 容…

ubuntu部署sonar与windows下使用sonar-scanner

ubuntu部署sonar与windows下使用sonar-scanner sonar部署java安装mysql安装配置sonarqube 插件安装sonar-scanner使用简单使用 sonar部署 使用的是sonarqube-7.5&#xff0c;支持的java环境是jdk8&#xff0c;且MySQL版本 >5.6 && <8.0 java安装 打开终端&…
最新文章