news 2026/9/3 6:29:35

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/9/2 23:24:10

[特殊字符] Web-Check:一站式开源网站侦查工具

Web-Check&#xff1a;强大的网站分析工具 Web-Check 是一款全功能的开源情报工具&#xff0c;旨在分析任何网站的内部工作。它可以帮助用户揭示潜在的攻击面&#xff0c;分析服务器架构&#xff0c;查看安全配置&#xff0c;并了解网站使用的技术。Web-Check 提供了全面的、按…

作者头像 李华
网站建设 2026/9/3 1:23:02

Unity 的AI Navigation 系统详细总结

Unity 的AI Navigation 系统&#xff08;2022.2 及以上版本通过 AI Navigation 包实现&#xff09;可让角色在游戏世界智能导航&#xff0c;核心基于自动生成的导航网格&#xff08;NavMesh&#xff09; &#xff0c;支持动态障碍物实时调整导航、OffMesh Link实现跳跃 / 开门等…

作者头像 李华
网站建设 2026/9/3 0:43:32

Unity3D AI Navigation 完全指南:从基础到实战,让角色智能导航

在 Unity 开发中&#xff0c;让游戏角色自主避开障碍、找到最优路径&#xff0c;是提升玩法体验的关键。Unity 的 AI Navigation 系统&#xff08;2022.2 版本已整合为 AI Navigation 包&#xff09;通过导航网格&#xff08;NavMesh&#xff09;、智能 Agent 和动态障碍物机制…

作者头像 李华
网站建设 2026/9/2 23:55:48

统信系统安装deb软件实用方法

文章目录背景知识学习安装命令单个安装批量安装安装位置背景 最近有台统信操作系统的电脑&#xff0c;需要安装补丁&#xff0c;如何安装呢&#xff0c;记录步骤&#xff0c;方便备查。 知识学习 统信操作系统是基于Ubuntu开发&#xff0c;有多种安装方式&#xff0c;在线安…

作者头像 李华
网站建设 2026/9/3 4:58:09

Stable Diffusion安全检测新玩法:GPU云端2块钱生成并分析恶意图片

Stable Diffusion安全检测新玩法&#xff1a;GPU云端2块钱生成并分析恶意图片 引言&#xff1a;当AI生成技术遇上安全检测 想象一下&#xff0c;你是一名网络安全研究员&#xff0c;最近发现黑客开始利用AI生成的图片传播恶意代码。传统的检测方法对这些新型威胁束手无策&…

作者头像 李华
网站建设 2026/9/2 23:56:12

跨平台用户画像构建:多源数据实体对齐,隐私合规

跨平台用户画像构建&#xff1a;多源数据实体对齐与隐私合规实践指南 引言&#xff1a;当广告技术遇上隐私合规挑战 想象一下你经营着一家连锁咖啡店&#xff0c;每位顾客可能通过小程序下单、在官网浏览新品、到实体店使用会员卡消费。如何把这些分散的行为串联起来&#xf…

作者头像 李华