本文源码:GitHub·点这里 || GitEE·点这里

一、生活场景

1、文件系统

下图是常见的计算机文件系统的一部分。

文件系统是一个树结构,树上长有节点。树的节点有两种:

  • 树枝节点

即文件夹,有内部树结构,在图中涂有颜色;

  • 树叶节点

另一种是文件,即树叶节点,没有内部树结构。

2、打印文件树结构

  1. public class C01_InScene {
  2. public static void main(String[] args) {
  3. File file = new File("F:\\tree") ;
  4. fileTree(file, 0);
  5. }
  6. private static void fileTree(File file, int floor) {
  7. // 判断是否存在
  8. if (file.exists()) {
  9. if (floor > 0) {
  10. // 循环打空格
  11. for (int i = 0; i < floor; i++) {
  12. System.out.print(" ");
  13. }
  14. }
  15. if (file.isDirectory()) {
  16. System.out.println("+" + file.getName());
  17. // 列出所有文件及文件夹
  18. File[] files = file.listFiles();
  19. if (null != files) {
  20. // 循环递归
  21. for (File dirFile : files) {
  22. fileTree(dirFile, floor + 1);
  23. }
  24. }
  25. } else {
  26. System.out.println("-" + file.getName());
  27. }
  28. }
  29. }
  30. }

执行效果:+代表文件夹,-代表文件。

  1. +tree
  2. +dir1
  3. +dir2
  4. -dir2Leaf.txt
  5. -leaf1.txt
  6. -leaf2.txt
  7. -OneLeaf.txt
  8. -TwoLeaf.txt

3、组合模式描述

组合模式属于对象的结构模式,有时又叫做“部分——整体”模式。组合模式将对象组织到树结构中,可以用来描述整体与部分的关系。组合模式可以使客户端将单纯元素与复合元素同等看待。

二、组合模式-安全式

1、基础概念

安全式的组合模式要求管理聚集的方法只出现在树枝构件类中,而不出现在树叶构件类中。涉及到三个角色:

  • 抽象构件(Component)角色

它给组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。组合对象通常把它所包含的子对象当做类型为Component的对象。在安全式的组合模式里,构件角色并不定义出管理子对象的方法,这一定义由树枝构件对象给出。

  • 树叶构件(Leaf)角色

树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。

  • 树枝构件(Composite)角色

代表参加组合的有下级子对象的对象。树枝构件类给出所有的管理子对象的方法,如add()、remove()以及getChild()。

2、模式图解

3、源代码实现

  1. public class C02_Security_Model {
  2. public static void main(String[] args) {
  3. Composite root = new Composite("服装");
  4. Composite composite1 = new Composite("男装");
  5. Leaf manCoat = new Leaf("上衣");
  6. Leaf manBottom = new Leaf("下衣");
  7. composite1.addChild(manCoat);
  8. composite1.addChild(manBottom);
  9. Composite composite2 = new Composite("女装");
  10. Leaf leaf1 = new Leaf("鞋子");
  11. Leaf leaf2 = new Leaf("帽子");
  12. root.addChild(leaf1);
  13. root.addChild(leaf2);
  14. root.addChild(composite1);
  15. root.addChild(composite2);
  16. root.printStruct("");
  17. }
  18. }
  19. // 抽象构件角色类
  20. interface Component {
  21. /*
  22. * 输出组件自身的名称
  23. */
  24. void printStruct(String preStr);
  25. }
  26. // 树枝构件角色类
  27. class Composite implements Component{
  28. // 用来存储组合对象中包含的子组件对象
  29. private List<Component> childComponents = new ArrayList<Component>();
  30. // 输出对象的名称
  31. private String name;
  32. // 构造方法,传入组合对象的名字
  33. public Composite (String name){
  34. this.name = name;
  35. }
  36. /**
  37. * 聚集管理方法,增加一个子构件对象
  38. * @param child 子构件对象
  39. */
  40. public void addChild(Component child){
  41. childComponents.add(child);
  42. }
  43. /**
  44. * 聚集管理方法,删除一个子构件对象
  45. * @param index 子构件对象的下标
  46. */
  47. public void removeChild(int index){
  48. childComponents.remove(index);
  49. }
  50. /**
  51. * 聚集管理方法,返回所有子构件对象
  52. */
  53. public List getChild(){
  54. return childComponents ;
  55. }
  56. /**
  57. * 输出对象的自身结构
  58. * @param preStr 前缀,主要是按照层级拼接空格,实现向后缩进
  59. */
  60. @Override
  61. public void printStruct(String preStr) {
  62. //先输出自己
  63. System.out.println(preStr+"+"+this.name);
  64. //如果还包含有子组件,那么就输出这些子组件对象
  65. if (this.childComponents != null){
  66. //添加两个空格,表示向后缩进两个空格
  67. preStr = preStr+" ";
  68. //输出当前的子对象:使用函数递归的原理
  69. for (Component c : childComponents) {
  70. c.printStruct(preStr);
  71. }
  72. }
  73. }
  74. }
  75. class Leaf implements Component{
  76. // 输出叶子对象的名称
  77. private String name;
  78. // 构造方法,传入叶子对象的名称
  79. public Leaf (String name){
  80. this.name = name ;
  81. }
  82. /**
  83. * 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字
  84. * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
  85. */
  86. @Override
  87. public void printStruct(String preStr) {
  88. System.out.println(preStr+"-"+name);
  89. }
  90. }
  • 输出结果
  1. +服装
  2. -鞋子
  3. -帽子
  4. +男装
  5. -上衣
  6. -下衣
  7. +女装

三、组合模式-透明式

1、概念图解

与安全式的组合模式不同的是,透明式的组合模式要求所有的具体构件类,不论树枝构件还是树叶构件,均符合一个固定接口。

2、源代码实现

  1. public class C03_Transparent_Model {
  2. public static void main(String[] args) {
  3. Component1 root = new Composite1("服装");
  4. Component1 c1 = new Composite1("男装");
  5. Component1 c2 = new Composite1("女装");
  6. Component1 leaf1 = new Leaf1("衬衫");
  7. Component1 leaf2 = new Leaf1("夹克");
  8. Component1 leaf3 = new Leaf1("裙子");
  9. Component1 leaf4 = new Leaf1("套装");
  10. root.addChild(c1);
  11. root.addChild(c2);
  12. c1.addChild(leaf1);
  13. c1.addChild(leaf2);
  14. c2.addChild(leaf3);
  15. c2.addChild(leaf4);
  16. root.printStruct("");
  17. }
  18. }
  19. abstract class Component1 {
  20. /**
  21. * 输出组件自身的名称
  22. */
  23. public abstract void printStruct(String preStr);
  24. // 聚集管理方法,增加一个子构件对象
  25. public void addChild(Component1 child){
  26. /**
  27. * 缺省实现,抛出异常,因为叶子对象没有此功能
  28. * 或者子组件没有实现这个功能
  29. */
  30. throw new UnsupportedOperationException("对象不支持此功能");
  31. }
  32. // 聚集管理方法,删除一个子构件对象
  33. public void removeChild(int index){
  34. /**
  35. * 缺省实现,抛出异常,因为叶子对象没有此功能
  36. * 或者子组件没有实现这个功能
  37. */
  38. throw new UnsupportedOperationException("对象不支持此功能");
  39. }
  40. // 聚集管理方法,返回所有子构件对象
  41. public List<Component1> getChild(){
  42. /**
  43. * 缺省实现,抛出异常,因为叶子对象没有此功能
  44. * 或者子组件没有实现这个功能
  45. */
  46. throw new UnsupportedOperationException("对象不支持此功能");
  47. }
  48. }
  49. class Composite1 extends Component1 {
  50. // 用来存储组合对象中包含的子组件对象
  51. private List<Component1> childComponents = new ArrayList<Component1>();
  52. // 输出对象名称
  53. private String name ;
  54. public Composite1 (String name){
  55. this.name = name;
  56. }
  57. /**
  58. * 聚集管理方法,增加一个子构件对象
  59. * @param child 子构件对象
  60. */
  61. public void addChild(Component1 child){
  62. childComponents.add(child);
  63. }
  64. /**
  65. * 聚集管理方法,删除一个子构件对象
  66. * @param index 子构件对象的下标
  67. */
  68. public void removeChild(int index){
  69. childComponents.remove(index);
  70. }
  71. // 聚集管理方法,返回所有子构件对象
  72. public List<Component1> getChild(){
  73. return childComponents ;
  74. }
  75. /**
  76. * 输出对象的自身结构
  77. * @param preStr 前缀,主要是按照层级拼接空格,实现向后缩进
  78. */
  79. @Override
  80. public void printStruct(String preStr) {
  81. // 首先输出自己名称
  82. System.out.println(preStr+"+"+this.name);
  83. // 如果还包含有子组件,那么就输出这些子组件对象
  84. preStr = preStr + " ";
  85. if (this.childComponents != null) {
  86. // 添加两个空格,表示向后缩进
  87. for (Component1 c : childComponents) {
  88. ////递归输出每个子对象
  89. c.printStruct(preStr);
  90. }
  91. }
  92. }
  93. }
  94. class Leaf1 extends Component1 {
  95. private String name;
  96. public Leaf1 (String name){
  97. this.name = name;
  98. }
  99. /**
  100. * 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字
  101. * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
  102. */
  103. @Override
  104. public void printStruct(String preStr) {
  105. System.out.println(preStr+"-"+name);
  106. }
  107. }

四、JDK中应用

1、HashMap结构图

2、分层结构

  • interface Map
  • class AbstractMap implements Map
  • HashMap extends AbstractMap implements Map
  • interface Map.Entry
  • Node implements Map.Entry

3、源代码

  • 存储叶子节点
  1. public V put(K var1, V var2) {
  2. return this.putVal(hash(var1), var1, var2, false, true);
  3. }
  4. final V putVal(int var1, K var2, V var3, boolean var4, boolean var5) {
  5. HashMap.Node[] var6 = this.table;
  6. .......
  7. }
  • 存储树枝节点
  1. public void putAll(Map<? extends K, ? extends V> var1) {
  2. this.putMapEntries(var1, true);
  3. }

五、源代码地址

  1. GitHub·地址
  2. https://github.com/cicadasmile/model-arithmetic-parent
  3. GitEE·地址
  4. https://gitee.com/cicadasmile/model-arithmetic-parent

Java描述设计模式(10):组合模式的更多相关文章

  1. C#设计模式(10)——组合模式(Composite Pattern)

    一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...

  2. C#设计模式(10)——组合模式(Composite Pattern)(转)

    一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...

  3. C#设计模式(10)——组合模式

    一.概念 组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦. 二.组 ...

  4. 基于JAVA的设计模式之组合模式

    概念 将所有对象组合成一种树形结构,有分支节点.叶子节点,分支节点可以有自己的子节点,子节点可以是分支节点.叶子节点,可以进行增删的操作,而叶子节点不可以.比如文件夹就是一个分支节点,而文件就是一个叶 ...

  5. JavaScript设计模式之----组合模式

    javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...

  6. c++设计模式15 --组合模式

    今天研究了一下设计模式15 组合模式 本人是菜鸟一枚,所以一开始完全不懂组合究竟是什么意思.先上图一张,树形结构图: 文档说,如果想做出这样的结构,通常考虑组合模式.那是为什么呢?现在让我们看一下组合 ...

  7. 乐在其中设计模式(C#) - 组合模式(Composite Pattern)

    原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ...

  8. C#设计模式:组合模式(Composite Pattern)

    一,C#设计模式:组合模式(Composite Pattern) using System; using System.Collections.Generic; using System.Linq; ...

  9. 设计模式之组合模式——Java语言描述

    组合模式又叫做部分整体模式,适用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次 介绍 意图 将对象组合成树形结构以表示"部分-整体" ...

随机推荐

  1. Java 判断密码是否是大小写字母、数字、特殊字符中的至少三种

    public class CheckPassword { //数字 public static final String REG_NUMBER = ".*\\d+.*"; //小写 ...

  2. ES6 promise 使用示例

    new Promise(function (resolve, reject) { $.ajax({ type : 'post', data : formData, dataType : 'json', ...

  3. 如何解决两个span标签之间的缝隙

    1.span直接一行 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> ...

  4. SVN重新定位操作流程

    因服务器其他系统需要SVN原来使用的443端口无法继续使用需要更换,服务器SVN端口已更新为8443,现将个人电脑SVN文件夹路径重新定位流程展示如下: 确定即修改成功!

  5. 面试连环炮系列(二十三): StringBuffer与StringBuild的区别

    StringBuffer与StringBuild的区别 频繁修改字符串时,建议使用StringBuffer和StringBuilder类.StringBuilder相较于StringBuffer有速度 ...

  6. python GUI编程tkinter示例之目录树遍历工具

    摘录 python核心编程 本节我们将展示一个中级的tkinter应用实例,这个应用是一个目录树遍历工具:它会从当前目录开始,提供一个文件列表,双击列表中任意的其他目录,就会使得工具切换到新目录中,用 ...

  7. c++-面向对象类的示例-求周长面积,判断体积相等-文件操作和一般操作

    面向对象编程示例:求周长和面积 #define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; //圆的周 ...

  8. SAP MM ME57界面看到的供应源跟Source List主数据不一致?

    SAP MM ME57界面看到的供应源跟Source List主数据不一致? ME57,为如下的PR单据分配供应源, 发现找不到想要分配的供应源. ME03 去看Source List主数据, 黄色标 ...

  9. R语言学习-基础篇1

    ###第一周:R基础 rm(list = ls())  #ctr+L###矩阵相乘,函数diag()a=matrix(1:12,nrow=3,ncol=4)b=matrix(1:12,nrow=4,n ...

  10. IT兄弟连 HTML5教程 W3C盒子模型

    日常生活中所见的盒子也就是能装东西的一种箱子,如果家里的东西很多,那么就需要按类别装到不同的箱子中.网页中的内容表现也是一样的,如果页面内容比较多,又想让页面更整洁.更美观.有很好的用户体验,则也需要 ...