目录

一、定义

二、组合模式案例分析

三、组合模式应用分析

四、总结


一、定义

组合模式,也叫合成模式,有时又叫做部分 - 整体模式,主要是用来描述部分与整体的关系,其定义如下:将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

组合模式使得客户端不需要区分哪些是叶子,哪些是容器节点,都使用统一的方式进行处理,极大地方便了客户端的调用。组合模式属于结构性模式。

组合模式的通用类图如下:

先来说说组合模式的几个角色:

  • Component抽象构件角色:定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性,可以是接口或抽象类;
  • Leaf叶子构件:叶子节点是最后一层节点,下面不包含其他子节点,它需要实现抽象构件类Componnet中定义的抽象方法;
  • Composite树枝构件:子容器,里面持有一个抽象构件的引用,可以是子容器节点,也可以是叶子节点,使用集合存储子节点
  • Client:客户端依赖抽象构件,一致对待子容器节点和叶子节点;

二、组合模式案例分析

我们以一个学校的组织架构树来说明组合模式的使用:

一个学校包含多个学院,一个学院包含多个部门,部门是最下面一级,不能包含其他子节点,即部门是叶子节点,需要展示整个学校的组织架构树;

如果不使用组合模式实现的话,我们首先想到的就是使用继承来实现上面的需求,虽然能够解决问题,但是实际上学院和学院之间、学院和部门之间并不是真正存在父子关系,所以使用继承方式实现不太合理。

首先看一下整体的类图:

回顾一下,前面提到组合模式涉及的三个角色:抽象构件Component、叶子构件、Composite树枝构件。首先我们需要定义抽象构件角色,它是一个抽象类,包含了添加、删除子构件的方法,具体代码如下:

/*** @Description: 学院组织(组合部件)* @Author: weixiaohuai* @Date: 2019/11/12* @Time: 20:21*/
public abstract class SchoolOrganizationComponent {/*** 名称*/private String name;public SchoolOrganizationComponent(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}protected void add(SchoolOrganizationComponent component) {}protected void delete(SchoolOrganizationComponent component) {}public abstract void print();
}

接着定义树枝节点,前面分析到,学校是顶级树节点、学院是属于学校下面的树枝节点,学校、学院树枝构件的定义如下:

/*** @Description: 学校类* @Author: weixiaohuai* @Date: 2019/11/12* @Time: 20:25*/
public class School extends SchoolOrganizationComponent {/*** 学校包含多个学院,这里使用超类SchoolOrganizationComponent替代子类College*/private List<SchoolOrganizationComponent> components = new ArrayList<>();public School(String name) {super(name);}@Overrideprotected void add(SchoolOrganizationComponent component) {components.add(component);}@Overrideprotected void delete(SchoolOrganizationComponent component) {components.remove(component);}/*** 输出学校里面的所有学院*/@Overridepublic void print() {for (SchoolOrganizationComponent component : components) {component.print();}}}/*** @Description: 学院类,一个学院包括多个部门* @Author: weixiaohuai* @Date: 2019/11/12* @Time: 20:33*/
public class College extends SchoolOrganizationComponent {/*** 存在部门信息*/private List<SchoolOrganizationComponent> components = new ArrayList<>();public College(String name) {super(name);}@Overrideprotected void add(SchoolOrganizationComponent component) {components.add(component);}@Overrideprotected void delete(SchoolOrganizationComponent component) {components.remove(component);}@Overridepublic void print() {for (SchoolOrganizationComponent c : components) {c.print();}}
}

注意学校、学院树枝节点内部都持有一个抽象构件的引用。

最后我们定义叶子角色,也就是学院下面的部门,具体代码如下:

public class Department extends SchoolOrganizationComponent {public Department(String name) {super(name);}@Overrideprotected void add(SchoolOrganizationComponent component) {System.out.println("不支持该方法...");}@Overrideprotected void delete(SchoolOrganizationComponent component) {System.out.println("不支持该方法...");}@Overridepublic void print() {System.out.println(getName());}}

由于叶子角色下面不存在节点,所以内部的添加子节点、删除子节点的方法,需要空实现或者抛出不支持该操作的异常,让高层模块知道叶子节点不支持添加子节点。

最后,我们定义一个场景类,来看看如何使用:

public class Client {public static void main(String[] args) {//学校SchoolOrganizationComponent university = new School("中山大学");//学院里面添加多个部门SchoolOrganizationComponent college1 = new College("计算机学院");college1.add(new Department("计算机专业"));college1.add(new Department("软件工程专业"));SchoolOrganizationComponent college2 = new College("文学院");college2.add(new Department("语文专业"));college2.add(new Department("文学专业"));//学校里面添加多个学院university.add(college1);university.add(college2);System.out.println("====" + university.getName() + "====");university.print();System.out.println("====" + college1.getName() + "====");college1.print();System.out.println("====" + college2.getName() + "====");college2.print();}
}

运行结果如下:

可以看到,高层模块使用的时候不需要区分当前是子容器对象还是叶子节点,都采用一致的方式调用,这样极大地方便客户端的调用。

三、组合模式应用分析

在JDK中有挺多地方使用到组合模式的,其中大家比较熟悉的List中的addAll(Collection<? extends E> c)方法和Map中putAll()方法(HashMap是Composite,Map是抽象构建,Map中静态内部类Node是叶子节点)都使用到了组合模式,下面我们以List的addAll(Collection<? extends E> c)方法大概分析一下组合模式在其中的应用:

public class Test {public static void main(String[] args) {List<String> allList = new ArrayList<>();allList.add("a");List<String> subList = new ArrayList<>();subList.add("b");subList.add("c");allList.addAll(subList);// addAll(Collection<? extends E> c) : 使用了组合模式// public interface List<E> extends Collection<E> : List接口继承Collection// 抽象构建Component: Collection// 组合类Composite: List// addAll方法源码// public boolean addAll(Collection<? extends E> c) {// List转换为数组// Object[] a = c.toArray();// 计算数组长度// int numNew = a.length;// 扩容// ensureCapacityInternal(size + numNew); // Increments modCount// 数组拷贝// System.arraycopy(a, 0, elementData, size, numNew);// size += numNew;// return numNew != 0;// }for (String string : allList) {System.out.println(string);}}

四、总结

组合模式的优点:

  • 客户端不需要关注具体是叶子节点还是子容器节点,方便对各个对象进行统一控制;
  • 增加新的子容器节点和叶子节点都挺方便,不需要对原有代码进行改造,符合开闭原则;
  • 通过叶子节点和子容器节点的递归组合可以形成复杂的树形结构数据,但对于树形结构的控制却很简单;

组合模式的缺点:

  • 客户端需要花很多时间去理清类之间的层次关系;

组合模式的使用场景:

  • 在具有整体和部分的层次结构中希望通过一种忽略整体与个体之间差异的,客户端一致对待的情况;
  • 需要遍历组织机构,处理一个树形结构对象时,可以考虑使用组合模式;
  • 如果叶子节点和子容器之间差异比较大,那么不太适合使用组合模式;

设计模式 (九) 组合模式相关推荐

  1. 每天一个设计模式之组合模式

    作者按:<每天一个设计模式>旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现.诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) ...

  2. 1、【设计模式】组合模式

    java设计模式之组合模式 [学习难度:★★★☆☆,使用频率:★★★★☆]  树形结构在软件中随处可见,例如操作系统中的目录结构.应用软件中的菜单.办公系统中的公司组织结构等等,如何运用面向对象的方式 ...

  3. 详解设计模式:组合模式

    组合模式(Composite Pattern),又叫部分整体模式,是 GoF 的 23 种设计模式中的一种结构型设计模式. 组合模式 是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组 ...

  4. 结构型设计模式之组合模式

    结构型设计模式之组合模式 组合模式 应用场景 优缺点 主要角色 组合模式结构 分类 透明组合模式 创建抽象根节点 创建树枝节点 创建叶子节点 客户端调用 安全组合模式 创建抽象根节点 创建树枝节点 创 ...

  5. java设计模式之组合模式(树形层级)

    java设计模式之组合模式 学习难度:★★★☆☆,使用频率:★★★★☆]  树形结构在软件中随处可见,例如操作系统中的目录结构.应用软件中的菜单.办公系统中的公司组织结构等等,如何运用面向对象的方式来 ...

  6. Java设计模式之组合模式详解

    文章目录 详解Java设计模式之组合模式 案例引入 组合模式 定义 模式类图结构 相关角色 典型代码 案例分析 类图设计 实例代码 结果分析 JavaJDK中的组合模式 透明组合模式 安全组合模式 组 ...

  7. Java设计模式之组合模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  8. (九)Java架构师成长之路-设计模式:组合模式

    一.定义 组合模式也叫整体-部分模式,目的是为了实现整体和部分都有一组相同的操作方法. 属于结构型模式 注意区别一下组合和聚合的区别: 组合:各部分组织结构有相同的生命周期,例如人的各个器官和人,人死 ...

  9. 设计模式之组合模式(Composite)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  10. 设计模式复习-组合模式

    #pragma once #include "stdafx.h" #include<set> #include<string> #include<io ...

最新文章

  1. 30岁前挣够500万
  2. Memcached内存池分析
  3. Epoch不仅过时,而且有害?Reddit机器学习板块展开讨论
  4. ActivityRouter
  5. python-9-IO编程
  6. 好用的 Markdown 编辑器 Typora【Window 、Linux 下的安装教程】
  7. 尝鲜体验 VS Code Python 原生 Jupyter Notebook 支持
  8. microsoft office 2007 完全 卸载 工具 来自微软官方
  9. Python基础(十): 函数的基本概念
  10. 堆排序python代码实现_八大排序算法的python实现(五)堆排序
  11. 堆栈小应用(一):括号匹配程序
  12. android 修改系统默认语言
  13. html流特性,CSS深入理解流体特性和BFC特性下多栏自适应布局_html/css_WEB-ITnose
  14. 计算机工程与应用论文模板,计算机工程与应用论文模板
  15. 智能家居APP使用指南
  16. php jpeg windows,jpg和jpeg有什么区别
  17. java 九九乘法表 99乘法表
  18. mfc 中文乱码转换为正常中文_MFC下遇到的字符集和中文乱码问题
  19. vue3缓存页面keep-alive+路由统一处理
  20. ENSP华为模拟器:基础命令及简写

热门文章

  1. linux静态网络带宽分配策略,Xen网络带宽分配优化方案的设计与实现
  2. 怎么批量调色_100款一键批量商业影楼修图调色PS动作,让你成为P图高手!!
  3. 算法:Jump Game
  4. Single Number 只出现一次的数字 python实现 - ...
  5. 387.字符串中的第一个唯一字符
  6. java求第几位数字_怎么得到一个数的第n位数字 急求大神帮助
  7. boost的时间和日期处理-(2)时间的操作
  8. 【 Codeforces Round #547 (Div. 3) G】Privatization of Roads in Treeland【树上贪心问题】
  9. 【BZOJ 1036】树的统计【树链剖分模板】
  10. 基础集合论 第一章 2 集合