news 2026/4/15 22:26:16

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/4/15 22:26:13

Nodejs+vue大学生二手闲置物品置换交易管理系统

文章目录摘要--nodejs技术栈--结论源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;摘要 该系统基于Node.js与Vue.js构建&#xff0c;旨在为大学生提供一个高效、安全的二手闲置物品交易平台。通过前后端分离架构&#xff0c;系统实现了…

作者头像 李华
网站建设 2026/4/9 4:23:20

Nodejs+vue大学生兼职应聘评分管理系统h4bmt

文章目录系统概述核心功能模块技术实现亮点应用价值--nodejs技术栈--结论源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统概述 Node.jsVue大学生兼职应聘评分管理系统&#xff08;H4BMT&#xff09;是一款基于前后端分离架构的Web应…

作者头像 李华
网站建设 2026/4/12 19:39:15

2025年上海交通大学计算机考研复试机试真题(解题思路 + AC 代码)

2025年上海交通大学计算机考研复试机试真题 2025年上海交通大学计算机考研复试上机真题 历年上海交通大学计算机考研复试上机真题 历年上海交通大学计算机考研复试机试真题 更多学校完整题目开源地址&#xff1a;https://gitcode.com/u014339447/pgcode 百度一下pgcode 即…

作者头像 李华
网站建设 2026/4/5 13:30:12

AI安全监控省钱技巧:按需启动节省80%成本

AI安全监控省钱技巧&#xff1a;按需启动节省80%成本 1. 为什么需要优化AI监控资源&#xff1f; 很多企业部署AI安全监控系统后发现一个普遍问题&#xff1a;夜间监控资源利用率极低&#xff0c;而白天又可能出现资源不足的情况。这就像买了一家24小时营业的便利店&#xff0…

作者头像 李华
网站建设 2026/4/7 3:44:39

大数据处理:分布式计算中的推测执行

大数据处理:分布式计算中的推测执行 关键词:大数据处理、分布式计算、推测执行、MapReduce、任务调度、容错机制、性能优化 摘要:本文深入探讨了大数据处理中分布式计算的推测执行机制。我们将从基本原理出发,详细分析推测执行在MapReduce等分布式计算框架中的应用,包括其…

作者头像 李华
网站建设 2026/3/26 19:41:36

matlab实时脚本算拉普拉斯反变换和画图

//////////////////////clcclose allclearsyms s tnum 80;den s^412*s^341*s^282*s80;Fs num/denres solve(den) %求解分母多项式等于 0 的根&#xff08;即特征根&#xff09;Ft simplify(ilaplace(Fs, s, t)) % %对 F(s)做拉普拉斯逆变换&#xff0c;将变量从拉普拉斯域…

作者头像 李华