Java描述设计模式(10):组合模式
本文源码:GitHub·点这里 || GitEE·点这里
一、生活场景
1、文件系统
下图是常见的计算机文件系统的一部分。

文件系统是一个树结构,树上长有节点。树的节点有两种:
- 树枝节点
即文件夹,有内部树结构,在图中涂有颜色;
- 树叶节点
另一种是文件,即树叶节点,没有内部树结构。
2、打印文件树结构
public class C01_InScene {
    public static void main(String[] args) {
        File file = new File("F:\\tree") ;
        fileTree(file, 0);
    }
    private static void fileTree(File file, int floor) {
        // 判断是否存在
        if (file.exists()) {
            if (floor > 0) {
                // 循环打空格
                for (int i = 0; i < floor; i++) {
                    System.out.print(" ");
                }
            }
            if (file.isDirectory()) {
                System.out.println("+" + file.getName());
                // 列出所有文件及文件夹
                File[] files = file.listFiles();
                if (null != files) {
                    // 循环递归
                    for (File dirFile : files) {
                        fileTree(dirFile, floor + 1);
                    }
                }
            } else {
                System.out.println("-" + file.getName());
            }
        }
    }
}
执行效果:+代表文件夹,-代表文件。
+tree
 +dir1
  +dir2
   -dir2Leaf.txt
  -leaf1.txt
  -leaf2.txt
 -OneLeaf.txt
 -TwoLeaf.txt
3、组合模式描述
组合模式属于对象的结构模式,有时又叫做“部分——整体”模式。组合模式将对象组织到树结构中,可以用来描述整体与部分的关系。组合模式可以使客户端将单纯元素与复合元素同等看待。
二、组合模式-安全式
1、基础概念
安全式的组合模式要求管理聚集的方法只出现在树枝构件类中,而不出现在树叶构件类中。涉及到三个角色:
- 抽象构件(Component)角色
它给组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。组合对象通常把它所包含的子对象当做类型为Component的对象。在安全式的组合模式里,构件角色并不定义出管理子对象的方法,这一定义由树枝构件对象给出。
- 树叶构件(Leaf)角色
树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。
- 树枝构件(Composite)角色
代表参加组合的有下级子对象的对象。树枝构件类给出所有的管理子对象的方法,如add()、remove()以及getChild()。
2、模式图解

3、源代码实现
public class C02_Security_Model {
    public static void main(String[] args) {
        Composite root = new Composite("服装");
        Composite composite1 = new Composite("男装");
        Leaf manCoat = new Leaf("上衣");
        Leaf manBottom = new Leaf("下衣");
        composite1.addChild(manCoat);
        composite1.addChild(manBottom);
        Composite composite2 = new Composite("女装");
        Leaf leaf1 = new Leaf("鞋子");
        Leaf leaf2 = new Leaf("帽子");
        root.addChild(leaf1);
        root.addChild(leaf2);
        root.addChild(composite1);
        root.addChild(composite2);
        root.printStruct("");
    }
}
// 抽象构件角色类
interface Component {
    /*
     * 输出组件自身的名称
     */
    void printStruct(String preStr);
}
// 树枝构件角色类
class Composite implements Component{
    // 用来存储组合对象中包含的子组件对象
    private List<Component> childComponents = new ArrayList<Component>();
    // 输出对象的名称
    private String name;
    // 构造方法,传入组合对象的名字
    public Composite (String name){
        this.name = name;
    }
    /**
     * 聚集管理方法,增加一个子构件对象
     * @param child 子构件对象
     */
    public void addChild(Component child){
        childComponents.add(child);
    }
    /**
     * 聚集管理方法,删除一个子构件对象
     * @param index 子构件对象的下标
     */
    public void removeChild(int index){
        childComponents.remove(index);
    }
    /**
     * 聚集管理方法,返回所有子构件对象
     */
    public List getChild(){
        return childComponents ;
    }
    /**
     * 输出对象的自身结构
     * @param preStr 前缀,主要是按照层级拼接空格,实现向后缩进
     */
    @Override
    public void printStruct(String preStr) {
        //先输出自己
        System.out.println(preStr+"+"+this.name);
        //如果还包含有子组件,那么就输出这些子组件对象
        if (this.childComponents != null){
            //添加两个空格,表示向后缩进两个空格
            preStr = preStr+"  ";
            //输出当前的子对象:使用函数递归的原理
            for (Component c : childComponents) {
                c.printStruct(preStr);
            }
        }
    }
}
class Leaf implements Component{
    // 输出叶子对象的名称
    private String name;
    // 构造方法,传入叶子对象的名称
    public Leaf (String name){
        this.name = name ;
    }
    /**
     * 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字
     * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
     */
    @Override
    public void printStruct(String preStr) {
        System.out.println(preStr+"-"+name);
    }
}
- 输出结果
+服装
  -鞋子
  -帽子
  +男装
    -上衣
    -下衣
  +女装
三、组合模式-透明式
1、概念图解
与安全式的组合模式不同的是,透明式的组合模式要求所有的具体构件类,不论树枝构件还是树叶构件,均符合一个固定接口。

2、源代码实现
public class C03_Transparent_Model {
    public static void main(String[] args) {
        Component1 root = new Composite1("服装");
        Component1 c1 = new Composite1("男装");
        Component1 c2 = new Composite1("女装");
        Component1 leaf1 = new Leaf1("衬衫");
        Component1 leaf2 = new Leaf1("夹克");
        Component1 leaf3 = new Leaf1("裙子");
        Component1 leaf4 = new Leaf1("套装");
        root.addChild(c1);
        root.addChild(c2);
        c1.addChild(leaf1);
        c1.addChild(leaf2);
        c2.addChild(leaf3);
        c2.addChild(leaf4);
        root.printStruct("");
    }
}
abstract class Component1 {
    /**
     * 输出组件自身的名称
     */
    public abstract void printStruct(String preStr);
    // 聚集管理方法,增加一个子构件对象
    public void addChild(Component1 child){
        /**
         * 缺省实现,抛出异常,因为叶子对象没有此功能
         * 或者子组件没有实现这个功能
         */
        throw new UnsupportedOperationException("对象不支持此功能");
    }
    // 聚集管理方法,删除一个子构件对象
    public void removeChild(int index){
        /**
         * 缺省实现,抛出异常,因为叶子对象没有此功能
         * 或者子组件没有实现这个功能
         */
        throw new UnsupportedOperationException("对象不支持此功能");
    }
    // 聚集管理方法,返回所有子构件对象
    public List<Component1> getChild(){
        /**
         * 缺省实现,抛出异常,因为叶子对象没有此功能
         * 或者子组件没有实现这个功能
         */
        throw new UnsupportedOperationException("对象不支持此功能");
    }
}
class Composite1 extends Component1 {
    // 用来存储组合对象中包含的子组件对象
    private List<Component1> childComponents = new ArrayList<Component1>();
    // 输出对象名称
    private String name ;
    public Composite1 (String name){
        this.name = name;
    }
    /**
     * 聚集管理方法,增加一个子构件对象
     * @param child 子构件对象
     */
    public void addChild(Component1 child){
        childComponents.add(child);
    }
    /**
     * 聚集管理方法,删除一个子构件对象
     * @param index 子构件对象的下标
     */
    public void removeChild(int index){
        childComponents.remove(index);
    }
    // 聚集管理方法,返回所有子构件对象
    public List<Component1> getChild(){
        return childComponents ;
    }
    /**
     * 输出对象的自身结构
     * @param preStr 前缀,主要是按照层级拼接空格,实现向后缩进
     */
    @Override
    public void printStruct(String preStr) {
        // 首先输出自己名称
        System.out.println(preStr+"+"+this.name);
        // 如果还包含有子组件,那么就输出这些子组件对象
        preStr = preStr + "  ";
        if (this.childComponents != null) {
            // 添加两个空格,表示向后缩进
            for (Component1 c : childComponents) {
                ////递归输出每个子对象
                c.printStruct(preStr);
            }
        }
    }
}
class Leaf1 extends Component1 {
    private String name;
    public Leaf1 (String name){
        this.name = name;
    }
    /**
     * 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字
     * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
     */
    @Override
    public void printStruct(String preStr) {
        System.out.println(preStr+"-"+name);
    }
}
四、JDK中应用
1、HashMap结构图

2、分层结构
- interface Map
- class AbstractMap implements Map
- HashMap extends AbstractMap implements Map
- interface Map.Entry
- Node implements Map.Entry
3、源代码
- 存储叶子节点
public V put(K var1, V var2) {
    return this.putVal(hash(var1), var1, var2, false, true);
}
final V putVal(int var1, K var2, V var3, boolean var4, boolean var5) {
    HashMap.Node[] var6 = this.table;
    .......
}
- 存储树枝节点
public void putAll(Map<? extends K, ? extends V> var1) {
    this.putMapEntries(var1, true);
}
五、源代码地址
GitHub·地址
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·地址
https://gitee.com/cicadasmile/model-arithmetic-parent

Java描述设计模式(10):组合模式的更多相关文章
- C#设计模式(10)——组合模式(Composite Pattern)
		一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ... 
- C#设计模式(10)——组合模式(Composite Pattern)(转)
		一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ... 
- C#设计模式(10)——组合模式
		一.概念 组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦. 二.组 ... 
- 基于JAVA的设计模式之组合模式
		概念 将所有对象组合成一种树形结构,有分支节点.叶子节点,分支节点可以有自己的子节点,子节点可以是分支节点.叶子节点,可以进行增删的操作,而叶子节点不可以.比如文件夹就是一个分支节点,而文件就是一个叶 ... 
- JavaScript设计模式之----组合模式
		javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ... 
- c++设计模式15 --组合模式
		今天研究了一下设计模式15 组合模式 本人是菜鸟一枚,所以一开始完全不懂组合究竟是什么意思.先上图一张,树形结构图: 文档说,如果想做出这样的结构,通常考虑组合模式.那是为什么呢?现在让我们看一下组合 ... 
- 乐在其中设计模式(C#) - 组合模式(Composite Pattern)
		原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ... 
- C#设计模式:组合模式(Composite Pattern)
		一,C#设计模式:组合模式(Composite Pattern) using System; using System.Collections.Generic; using System.Linq; ... 
- 设计模式之组合模式——Java语言描述
		组合模式又叫做部分整体模式,适用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次 介绍 意图 将对象组合成树形结构以表示"部分-整体" ... 
随机推荐
- 《一头扎进》系列之Python+Selenium框架设计篇3- 价值好几K的框架,狼来了,狼来了....,狼没来,框架真的来了
			1. 简介 前边宏哥一边一边的喊框架,就如同一边一边的喊狼来了!狼来了!.....这回是狼没有来,框架真的来了.从本文开始宏哥将会一步一步介绍,如何从无到有地创建自己的第一个自动化测试框架.这一篇,我 ... 
- 在C#中将对象序列化成Json格式
			在C#中将对象转换为Json格式的字符串. //匿名对象 var dataObj = new { Number = 1, Name = "Json" }; //将返回的时间格式解析 ... 
- The Preliminary Contest for ICPC Asia Xuzhou 2019
			A:Who is better? 题目链接:https://nanti.jisuanke.com/t/41383 题意: 类似于有N个石子,先手第一次不能拿完,每次后手只能拿 1 到 前一次拿的数量* ... 
- c++之基础数据类型
			c++规定了在创建一个变量或者常量时,必须先要指定相应的数据类型,否发无法将变量分配给内存. 1.整型 数据类型 占用空间 取值范围 short 2字节 -2^15-2^15-1 int 4字节 -2 ... 
- centos7.2中部署私有仓库harbor
			1.安装docker #安装依赖和驱动 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 #配置docker的官方源 s ... 
- Asp.net 学习记录(一)使用asp.net 构建webAPI接口
			此系列使用Asp.net构建前后端分离的博客网站. 创建一个asp.net项目 我们这里使用的是空模板,把Https配置去掉(安全先不配置) 构建webapi接口有很多方法,在这里我们选择最简单的2种 ... 
- linux系统centos7安装最新版本nginx
			一.准备环境 1.安装centos,一般买一个阿里云测试 2.下载nginx,链接http://nginx.org/download/nginx-1.10.2.tar.gz 二.开始安装 1.cent ... 
- PromiseKit基本使用及源码解析
			Promise处理一系列异步操作的应用框架,能够保证顺序执行一系列异步操作,当出错时可以通过catch捕获错误进行处理.Promise框架也是很好的诠释了swift的面相协议编程以及函数式编程 两种类 ... 
- 一 、爬虫的认识与http
			一 .爬虫的认识与http 互联网应用架构 一般采用c/s架构,b/s架构或者m/s架构 c/s 即 client server 客户端 服务端 b/s 即 browser server 浏览器 服 ... 
- 关于独显A卡利用率一直是0不运行的问题
			情况: 独显一直是0,玩游戏时核显,也就是GPU-0快满了GPU-1也是0,跟没有一样,怀疑自己买电脑的时候是不是被骗了. 在高级电源选项中,有个可切换动态显卡->全局设置的选项,设置成最大化性 ... 
