设计模式 --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.hqwc.cn/news/661319.html

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

相关文章

llama_index微调BGE模型

微调模型是为了让模型在特殊领域表现良好,帮助其学习到专业术语等。 本文采用llama_index框架微调BGE模型,跑通整个流程,并学习模型微调的方法。 一、环境准备 Linux环境,GPU L20 48G,Python3.8.10。 pip该库即可。 二、数据准备 该框架实现了读取各种类型的文件,给…

基于Spring Boot的校园博客系统设计与实现

基于Spring Boot的校园博客系统设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 系统功能界面图&#xff0c;在系统首页可以查看首页、文…

【webrtc】MessageHandler 5: 基于线程的消息处理:以PeerConnection信令线程为例

peerconn的信令是通过post 消息到自己的信令线程消息来处理的PeerConnectionMessageHandler 是具体的处理器G:\CDN\rtcCli\m98\src\pc\peer_connection_message_handler.hMachinery for handling messages posted to oneself PeerConnectionMessageHandler 明确服务于 signalin…

使用xshell工具连接ubuntu的root账户被拒绝的解决方法

问题描述&#xff1a; 我在使用xshell工具远程连接Ubuntu虚拟机的过程中&#xff0c;如果连接的是的普通用户则xshell工具可以正常连接&#xff0c;但是当我向连接ubuntu系统的root用户&#xff0c;即便是密码输入正确但还是不能连接成功。不能连接成功的截图如下&#xff1a; …

requests库进行接口请求

请求的常规写法 requests.post() 、requests.get() 从中可以看出&#xff1a; 必填参数&#xff1a; url可缺省参数&#xff1a; data&#xff0c;json等、关键字参数 **kwargs 如下进行了一个post请求的登录&#xff0c;且请求体在body中 知识点1 当为post请求时&#xff1…

python数据可视化:创建多个子图 matplotlib.pyplot.subplot()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 python数据可视化&#xff1a; 创建多个子图 matplotlib.pyplot.subplot() 请问关于以下代码表述正确的选项是&#xff1f; import matplotlib.pyplot as plt print("【执行】plt.subp…

Docker部署RabbitMQ与简单使用

官网地址&#xff1a; Messaging that just works — RabbitMQ 我的Docker博客:Docker-CSDN博客 1.结构 其中包含几个概念&#xff1a; **publisher**&#xff1a;生产者&#xff0c;也就是发送消息的一方 **consumer**&#xff1a;消费者&#xff0c;也就是消费消息的一方 …

【DeepL】菜鸟教程:如何申请DeepL免费API并使用Python的DeepL

前言 在这篇技术博文中,我们将介绍如何利用DeepL的强大功能,通过其免费API在Python项目中实现高质量的文本翻译。我们将从基础开始,解释DeepL是什么,它的用途,如何申请免费API,以及如何在Python中使用DeepL库。 什么是DeepL? DeepL是一个基于人工智能的翻译服务,它以…

【langchain】快速封装替换自定义LLM(基于自定义API或本地模型)

1. 引言 你可能已经注意到&#xff0c;LLM时代下的许多项目&#xff08;特别是Github上的论文项目、工程项目&#xff09;都要求我们设置OpenAI的API Key&#xff0c;就像这样&#xff1a; os.environ["OPENAI_API_KEY"] "sk-"from langchain_openai im…

【多模态大模型】AI对视频内容解析问答

文章目录 1. 项目背景2. 直接对视频进行解析进行AI问答&#xff1a;MiniGPT4-Video2.1 MiniGPT4-Video效果 3. 对视频抽帧为图片再进行AI问答3.1 视频抽帧3.2 图片AI问答3.2.1 阿里通义千问大模型 Qwen-vl-plus3.2.2 Moonshot 1. 项目背景 最近在做一个项目,需要使用AI技术对视…

【图论】图论基础

图论不同地方讲的不太一样&#xff0c;本文仅限作者的理解 定义 图一般由点集 V V V 和边集 E E E 组成。 对于 v ∈ V v\in V v∈V&#xff0c;称 v v v 为该图的一个节点。 对于 e ∈ E e\in E e∈E&#xff0c;一般用二元组 ( u , v ) (u,v) (u,v) 表示 e e e&…

如何批量修改文件的时间属性?修改创建时间,修改时间和访问时间

一&#xff0c;前言 在Excel中&#xff0c;修改文件的访问时间、创建时间和修改时间通常不是一个直接的功能。但是&#xff0c;我们可以通过一些间接的方法和工具来实现这一目标。请注意&#xff0c;直接修改这些时间戳可能会影响文件的完整性和安全性&#xff0c;因此在进行任…