news 2026/5/30 7:47:18

15.设计模式-组合模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
15.设计模式-组合模式

组合模式:将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

组合模式的两种实现:

  • 透明方式:在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等。这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的功能,所以实现它是没有意义的。
  • 安全方式:在Component接口中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,这样做就不会出现刚才提到的问题,不过由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。

需求


为一家在全国许多城市都有分销机构的大公司做办公管理系统,总部有人力资源、财务、运营等部门。

需求分析

  • 希望总公司的组织结构,比如人力资源部、财务部的管理功能可以复用于分公司

代码

业务类

#include<stdio.h>#include<stdlib.h>#include<string.h>typedefstructCompany{char*name;void(*add)(structCompany*,structCompany*);void(*remove)(structCompany*,structCompany*);void(*display)(structCompany*,int);void(*lineOfDuty)(structCompany*);}Company;typedefstructConcreteCompany{Company base;Company**children;intchildrenNum;}ConcreteCompany;voidConcreteCompanyAdd(Company*obj,Company*child){((ConcreteCompany*)obj)->children[((ConcreteCompany*)obj)->childrenNum++]=child;}voidConcreteCompanyRemove(Company*obj,Company*child){intn=((ConcreteCompany*)obj)->childrenNum;for(inti=0;i<n;i++){if(strcmp(((ConcreteCompany*)obj)->children[i]->name,child->name)==0){free(((ConcreteCompany*)obj)->children[i]);((ConcreteCompany*)obj)->children[i]=((ConcreteCompany*)obj)->children[((ConcreteCompany*)obj)->childrenNum-1];((ConcreteCompany*)obj)->childrenNum--;break;}}}voidConcreteCompanyDisplay(Company*obj,intdepth){for(inti=0;i<depth;i++){printf("-");}printf("%s\n",obj->name);intn=((ConcreteCompany*)obj)->childrenNum;for(inti=0;i<n;i++){((ConcreteCompany*)obj)->children[i]->display(((ConcreteCompany*)obj)->children[i],depth+1);}}voidConcreteCompanyLineOfDuty(Company*obj){intn=((ConcreteCompany*)obj)->childrenNum;for(inti=0;i<n;i++){((ConcreteCompany*)obj)->children[i]->lineOfDuty(((ConcreteCompany*)obj)->children[i]);}}Company*InitConcreteCompany(char*name){ConcreteCompany*obj=(ConcreteCompany*)malloc(sizeof(ConcreteCompany));obj->childrenNum=0;// 假设最多10个子公司和部门obj->children=(Company**)malloc(sizeof(Company*)*10);obj->base.name=name;obj->base.add=ConcreteCompanyAdd;obj->base.remove=ConcreteCompanyRemove;obj->base.display=ConcreteCompanyDisplay;obj->base.lineOfDuty=ConcreteCompanyLineOfDuty;return(Company*)obj;}typedefstructHRDepartment{Company base;}HRDepartment;voidHRDepartmentDisplay(Company*obj,intdepth){for(inti=0;i<depth;i++){printf("-");}printf("%s\n",obj->name);}voidHRDepartmentLineOfDuty(Company*obj){printf("%s 员工招聘培训管理\n",obj->name);}Company*InitHRDepartment(char*name){HRDepartment*obj=(HRDepartment*)malloc(sizeof(HRDepartment));obj->base.display=HRDepartmentDisplay;obj->base.lineOfDuty=HRDepartmentLineOfDuty;obj->base.name=name;return(Company*)obj;}typedefstructFinanceDepartment{Company base;}FinanceDepartment;voidFinanceDepartmentDisplay(Company*obj,intdepth){for(inti=0;i<depth;i++){printf("-");}printf("%s\n",obj->name);}voidFinanceDepartmentLineOfDuty(Company*obj){printf("%s 公司财务收支管理\n",obj->name);}Company*InitFinanceDepartment(char*name){FinanceDepartment*obj=(FinanceDepartment*)malloc(sizeof(FinanceDepartment));obj->base.display=FinanceDepartmentDisplay;obj->base.lineOfDuty=FinanceDepartmentLineOfDuty;obj->base.name=name;return(Company*)obj;}

客户端

隐藏子部门和分公司的区别

intmain(){Company*root=InitConcreteCompany("北京总公司");root->add(root,InitHRDepartment("总公司人力资源部"));root->add(root,InitFinanceDepartment("总公司财务部"));Company*comp=InitConcreteCompany("上海华东分公司");comp->add(comp,InitHRDepartment("华东分公司人力资源部"));comp->add(comp,InitFinanceDepartment("华东分公司财务部"));root->add(root,comp);Company*comp1=InitConcreteCompany("南京办事处");comp1->add(comp1,InitHRDepartment("南京办事处人力资源部"));comp1->add(comp1,InitFinanceDepartment("南京办事处财务部"));comp->add(comp,comp1);Company*comp2=InitConcreteCompany("杭州办事处");comp2->add(comp2,InitHRDepartment("杭州办事处人力资源部"));comp2->add(comp2,InitFinanceDepartment("杭州办事处财务部"));comp->add(comp,comp2);printf("结构图:\n");root->display(root,0);printf("职责:\n");root->lineOfDuty(root);return0;}

客户端打印:

结构图: 北京总公司 -总公司人力资源部 -总公司财务部 -上海华东分公司 --华东分公司人力资源部 --华东分公司财务部 --南京办事处 ---南京办事处人力资源部 ---南京办事处财务部 --杭州办事处 ---杭州办事处人力资源部 ---杭州办事处财务部 职责: 总公司人力资源部 员工招聘培训管理 总公司财务部 公司财务收支管理 华东分公司人力资源部 员工招聘培训管理 华东分公司财务部 公司财务收支管理 南京办事处人力资源部 员工招聘培训管理 南京办事处财务部 公司财务收支管理 杭州办事处人力资源部 员工招聘培训管理 杭州办事处财务部 公司财务收支管理

UML图

总结

  • 组合模式使用场景?
    “当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。”
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/25 1:26:02

导师不会告诉你的6个免费AI论文工具:1小时搞定全文告别熬夜

想知道为什么你隔壁实验室的同学总能提前交稿&#xff0c;而你还在一字一句地苦熬&#xff1f;因为他们在用一些“不该知道”的秘密武器。今天&#xff0c;我就来为你揭秘这些藏在水面之下的“学术黑科技”&#xff0c;特别是那个能让论文效率提升10倍的终极神器。 前言&#x…

作者头像 李华
网站建设 2026/5/21 23:39:47

计及多能耦合的区域综合能源系统电气热能流计算Matlab实现

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1f34…

作者头像 李华
网站建设 2026/5/22 4:41:02

AI侦测模型微调教程:云端GPU加速,3小时完成迭代

AI侦测模型微调教程&#xff1a;云端GPU加速&#xff0c;3小时完成迭代 引言 作为一名算法工程师&#xff0c;你是否遇到过这样的困境&#xff1a;公司GPU资源被其他项目占用&#xff0c;但你又急需优化行业专用模型&#xff1f;传统本地训练动辄需要数天时间&#xff0c;而项…

作者头像 李华
网站建设 2026/5/23 18:07:09

金融实体关系图谱构建:云端分布式计算,按需扩容

金融实体关系图谱构建&#xff1a;云端分布式计算&#xff0c;按需扩容 引言 作为一名反洗钱分析师&#xff0c;你是否经常遇到这样的困境&#xff1a;面对千万级的交易数据&#xff0c;本地电脑跑个简单的图计算都要卡死&#xff0c;更别提复杂的实体关系分析了&#xff1f;…

作者头像 李华
网站建设 2026/5/22 11:12:33

AI智能体游戏开发:独立制作人的智能NPC解决方案

AI智能体游戏开发&#xff1a;独立制作人的智能NPC解决方案 引言&#xff1a;为什么你的游戏需要智能NPC&#xff1f; 想象一下&#xff0c;你正在玩一款开放世界RPG游戏。当你走进酒馆时&#xff0c;里面的NPC&#xff08;非玩家角色&#xff09;不仅会机械地重复固定台词&a…

作者头像 李华
网站建设 2026/5/26 19:01:14

AI侦测技术体验馆:新模型第一时间尝鲜,不花冤枉钱

AI侦测技术体验馆&#xff1a;新模型第一时间尝鲜&#xff0c;不花冤枉钱 1. 为什么需要AI侦测技术体验馆 作为一名技术极客&#xff0c;每次看到arXiv上发布的新AI论文都跃跃欲试&#xff0c;但实际部署时总会遇到各种问题&#xff1a;环境配置冲突、依赖包版本不兼容、GPU资…

作者头像 李华