秒懂设计模式之组合模式(Composite Pattern)
[版权申明] 非商业目的注明出处可自由转载
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/116378002
出自:shusheng007
设计模式汇总篇,一定要收藏:
永不磨灭的设计模式(有这一篇真够了,拒绝标题党)
文章目录
- 概述
- 类型
- 难度
- 定义
- 使用场景
- UML类图
- 实例
- 第一,设计一个个体与组合通用的接口
- 第二,组合类
- 第三,叶子节点
- 第四,客户端
- 技术要点总结
- 优缺点
- 优点
- 缺点
- 总结
概述
组合模式出镜率不算特别高,但是一旦出境说明这个问题如果不使用它将变得非常困难。Android的View体系的设计方式就是组合模式非常经典的成功案例。
类型
结构型(structural)
难度
3颗星
定义
组合模式允许以相同的方式处理单个对象和对象的组合体
不理解不要紧,接着往下看
使用场景
- 当你的程序结构有类似树一样的层级关系时,例如文件系统,视图树,公司组织架构等等
- 当你要以统一的方式操作单个对象和由这些对象组成的组合对象的时候。
UML类图
从上图可见组合模式共有3组成部分
- Component
抽象类,定义统一的处理操作。
- Leaf
叶子节点,即单个对象
- Composite
组合对象,里面持有一个List<Component>
。
我们使用了组合模式中所谓的透明方式,因为我们将单个对象和组合对象按照完全一样的事物对待了,所以接口对外很透明。统一操作都是在Component
中定义的,所有继承至它的节点都要实现,而有些操作叶子节点是不支持的,例如添加移除节点等,这样就要求叶子节点处理好这些方法。
实例
林蛋大最近比较烦,公司新接了个外包IT项目,甲方是传统行业的老板,总是感觉这么简单的功能为什么要那么多钱,关键还慢…这不,刚刚要求蛋大写一个"小软件"用来管理公司的组织架构…
蛋大本来还想沟通下需求:王老板,这个活可大可小,您是不是想要…巴拉巴拉。把王老板烦的啊:小林啊,你别说了,我给你3天时间你去先做一个我看看,不行就再改嘛…。蛋大在心中怒了:老子姓楚!名中天… 做你mlgb,需求不给我做你mlgb… 但最后还是陪着笑脸说那我试试吧…
蛋大找王二狗帮忙出了个设计方案,此案例使用组合模式可解
第一,设计一个个体与组合通用的接口
定义对外展示的统一处理接口
public abstract class OrganizationComponent {private String name;public OrganizationComponent(String name) {this.name = name;}public String getName() {return name;}public abstract void add(OrganizationComponent organization);public abstract OrganizationComponent getChild(String orgName);public abstract int getStaffCount();@Overridepublic String toString() {return name;}
}
第二,组合类
此类持有一个List<OrganizationComponent>
,并继承OrganizationComponent
。
public class OrganizationComposite extends OrganizationComponent {//很关键,这体现了组合的思想private List<OrganizationComponent> organizations = new ArrayList<>();public OrganizationComposite(String name) {super(name);}@Overridepublic void add(OrganizationComponent organization) {organizations.add(organization);}@Overridepublic OrganizationComponent getChild(String orgName) {for (OrganizationComponent org : organizations) {OrganizationComponent targetOrg = org.getChild(orgName);if (targetOrg != null) {return targetOrg;}}return null;}@Overridepublic int getStaffCount() {int count = 0;for (OrganizationComponent organization : organizations) {count += organization.getStaffCount();}return count;}
}
第三,叶子节点
叶子节点就是单个对象了,我们要使用合适的方式处理那些叶子节点不支持的对外接口方法。因为用户使的时候只会看到对外暴露的统一接口,他不知道此对象是叶子节点还是组合对象。
public class ItDepartment extends OrganizationComponent {public ItDepartment(String name) {super(name);}@Overridepublic int getStaffCount() {return 20;}@Overridepublic void add(OrganizationComponent organization) {throw new UnsupportedOperationException(this.getName()+"已经是最基本部门,无法增加下属部门");}@Overridepublic OrganizationComponent getChild(String orgName) {if(getName().equals(orgName)){return this;}return null;}
}
// 其他叶子节点类似
...
第四,客户端
我们来看看是否达到了我们的设计目的:以统一的接口操作单个对象与其组合对象。
首先构建一个组合对象。模拟构建一家公司,公司下设行政部门和IT部门,还有一个天津分公司,而天津分公司又下设一个行政部门和IT部门。
然后我确定查询这个公司任何部门的员工人数。我们可以看到在查询过程中,我们没有判断当前对象到底是什么部门对象,都是以统一的接口在操作。
public class CompositeClient {private OrganizationComponent constructOrganization() {//构建总部OrganizationComposite head = new OrganizationComposite("总公司");AdminDepartment headAdmin = new AdminDepartment("总公司行政部");ItDepartment headIt = new ItDepartment("总公司It部");head.add(headAdmin);head.add(headIt);//构建分公司OrganizationComposite branch1 = new OrganizationComposite("天津分公司");AdminDepartment branch1Admin = new AdminDepartment("天津分公司行政部");ItDepartment branch1It = new ItDepartment("天津分公司It部");branch1.add(branch1Admin);branch1.add(branch1It);//将分公司加入到head中head.add(branch1);return head;}public void listOrgInfo() {OrganizationComponent org = constructOrganization();System.out.println(String.format("%s共有%d名员工",org.getName(), org.getStaffCount()));OrganizationComponent subOrg = org.getChild("天津分公司行政部");System.out.println(String.format("%s共有%d名员工",subOrg.getName(), subOrg.getStaffCount()));}
}
输出:
总公司共有140名员工
天津分公司行政部共有50名员工
技术要点总结
- 组合模式有所谓的透明方式与安全方式,是对于使用者而言的
透明方式将所有对外操作都放在Component
,叶子节点也得提供这些接口,虽然它实际上不支持这些操作。而安全方式只将叶子节点与组合对象同时提供的操作放在Component
。
为啥叫透明方式呢?因为用户使用的时候根本不管是叶子节点,还是组合对象,反正看到的接口都一样。这样就不安全了,因为万一这个对象是个叶子节点,假设你又使用了一个它不能提供的操作,例如add
,就出问题了…
- 通用操作定义在
Component
中,根据使用方式不同,透明方式与安全方式,有一定的不同 - 组合节点
Composite
不仅要继承Component
,而且要持有一个Component
的集合 - 叶子对象只继承
Component
即可
优缺点
优点
- 可以递归组合成任意复杂的对象
- 可随意增加新类型的
Composite
与Leaf
的类 - 简化了客户端代码,因为不论对象多么复杂客户端都是以同一套接口操作
缺点
- 如果需要确定某个组件是特殊组织,然后针对它做特殊的操作,就需要在运行时判断。
- 类多了
总结
设计模式值得你可以练习!
最后,如果你从本文中有所收获,可否点赞转发支持一下博主,你小小的鼓励,是激发博主持续写作的动力…
GitHub源码地址:design-patterns
秒懂设计模式之组合模式(Composite Pattern)相关推荐
- 【设计模式】组合模式 Composite Pattern
树形结构是软件行业很常见的一种结构,几乎随处可见, 比如: HTML 页面中的DOM,产品的分类,通常一些应用或网站的菜单,Windows Form 中的控件继承关系,Android中的View继承 ...
- python 设计模式之组合模式Composite Pattern
#引入一 文件夹对我们来说很熟悉,文件夹里面可以包含文件夹,也可以包含文件. 那么文件夹是个容器,文件夹里面的文件夹也是个容器,文件夹里面的文件是对象. 这是一个树形结构 咱们生活工作中常用的一种结构 ...
- C#设计模式——组合模式(Composite Pattern)
一.概述 在软件开发中,我们往往会遇上类似树形结构的对象体系.即某一对象既可能在树形结构中作为叶节点存在,也可能作为分支节点存在.比如在文件系统中,文件是作为叶节点存在,而文件夹就是分支节点.在设计这 ...
- 设计模式:组合模式(Composite Pattern)
组合模式: 又叫部分整体模式, 它创建了对象组的树形结构,将对象组合成树状结构以表示"整体-部分"的层次关系. JDK中的HashMap就使用了组合模式 public abstra ...
- 设计模式之组合模式(Composite)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- [设计模式] 8 组合模式 Composite
DP书上给出的定义:将对象组合成树形结构以表示"部分-整体"的层次结构.组合使得用户对单个对象和组合对象的使用具有一致性.注意两个字"树形".这种树形结构在现实 ...
- 24组合模式(Composite Pattern)
动机(Motivate): 组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元 ...
- 研磨设计模式 之 组合模式(Composite) 3——跟着cc学设计系列
15.3 模式讲解 15.3.1 认识组合模式 (1)组合模式的目的 组合模式的目的是:让客户端不再区分操作的是组合对象还是叶子对象,而是以一个统一的方式来操作. 实现这个目标的关键之处,是设计一 ...
- 研磨设计模式 之 组合模式(Composite) 2——跟着cc学设计系列
15.2 解决方案 15.2.1 组合模式来解决 用来解决上述问题的一个合理的解决方案就是组合模式.那么什么是组合模式呢? (1)组合模式定义 (2)应用组合模式来解决的思路 仔细分析上面不用模式 ...
最新文章
- 买个云服务器有啥用_如何用阿里云轻量应用服务器配置一个WordPress网站?
- html语言的空格键,如何在如何在HTML中插入空格中插入空格
- WPF Datagrid with some read-only rows - Stack Overflow
- 命令行验证apk签名
- ci 地址去掉index.php,CI框架如何删除地址栏的 index.php
- 14 FI配置-财务会计-定义未结清过帐期间变式
- Spark报错: Invalid Spark URL: spark://YarnScheduler@stream_test_nb:40659
- hibernate查询出的实体,set值后,自动更新到数据库
- Mac上翻译不在 Safari 中网站的方法
- 扩展MemberShip的使用:
- 全网最全-Java简历优化-专业技能
- 游戏软件测试用例编写范文,软件测试用例报告模板.doc
- 【路径规划】基于狼群算法之三维路径规划matlab源码
- 黑莓手机刷Linux系统,黑莓Priv系统刷机包下载及一键刷机方法步骤教程
- hive sql列转行
- 所谓的“互联网寒冬”,真的来了吗?
- 51单片机制作简易计算器(动态数码管、矩阵按键)
- w ndows10更改浏览器,Win10系统默认浏览器怎么修改
- 重装正版Windows系统
- Eclipse启动失败,提示查看.metadata文件夹下的.log文件