在阎宏博士的《JAVA与模式》一书中开头是这样描述合成(Composite)模式的:html

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

合成模式

合成模式把部分和总体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由它们复合而成的合成对象同等看待。安全

好比,一个文件系统就是一个典型的合成模式系统。下图是常见的计算机XP文件系统的一部分。ide

从上图能够看出,文件系统是一个树结构,树上长有节点。树的节点有两种,一种是树枝节点,即目录,有内部树结构,在图中涂有颜色;另外一种是文件,即树叶节点,没有内部树结构。post

显然,能够把目录和文件当作同一种对象同等对待和处理,这也就是合成模式的应用。this

合成模式能够不提供父对象的管理方法,可是合成模式必须在合适的地方提供子对象的管理方法,诸如:add()、remove()、以及getChild()等。url

合成模式的实现根据所实现接口的区别分为两种形式,分别称为安全式和透明式。spa

安全式合成模式的结构

安全模式的合成模式要求管理汇集的方法只出如今树枝构件类中,而不出如今树叶构件类中。

.net

这种形式涉及到三个角色:code

●  抽象构件(Component)角色:这是一个抽象角色,它给参加组合的对象定义出公共的接口及其默认行为,能够用来管理全部的子对象。合成对象一般把它所包含的子对象当作类型为Component的对象。在安全式的合成模式里,构件角色并不定义出管理子对象的方法,这必定义由树枝构件对象给出。

●  树叶构件(Leaf)角色:树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。

●  树枝构件(Composite)角色:表明参加组合的有下级子对象的对象。树枝构件类给出全部的管理子对象的方法,如add()、remove()以及getChild()。

源代码

抽象构件角色类

public interfaceComponent {

/*** 输出组建自身的名称 */ public voidprintStruct(String preStr); }

树枝构件角色类

public class Composite implementsComponent {

/*** 用来存储组合对象中包含的子组件对象 */ private List childComponents = new ArrayList(); /*** 组合对象的名字 */ privateString name; /*** 构造方法,传入组合对象的名字 * @paramname 组合对象的名字 */ publicComposite(String name){ this.name =name; } /*** 汇集管理方法,增长一个子构件对象 * @paramchild 子构件对象 */ public voidaddChild(Component child){ childComponents.add(child); } /*** 汇集管理方法,删除一个子构件对象 * @paramindex 子构件对象的下标 */ public void removeChild(intindex){ childComponents.remove(index); } /*** 汇集管理方法,返回全部子构件对象 */ public ListgetChild(){ returnchildComponents; } /*** 输出对象的自身结构 * @parampreStr 前缀,主要是按照层级拼接空格,实现向后缩进 */@Override public voidprintStruct(String preStr) { //先把本身输出 System.out.println(preStr + "+" + this.name); //若是还包含有子组件,那么就输出这些子组件对象 if(this.childComponents != null){ //添加两个空格,表示向后缩进两个空格 preStr += " "; //输出当前对象的子对象 for(Component c : childComponents){ //递归输出每一个子对象 c.printStruct(preStr); } } } }

树叶构件角色类

public class Leaf implementsComponent {

/*** 叶子对象的名字 */ privateString name; /*** 构造方法,传入叶子对象的名称 * @paramname 叶子对象的名字 */ publicLeaf(String name){ this.name =name; } /*** 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字 * @parampreStr 前缀,主要是按照层级拼接的空格,实现向后缩进 */@Override public voidprintStruct(String preStr) { //TODO Auto-generated method stub System.out.println(preStr + "-" +name); } }

客户端类

public classClient {

public static voidmain(String[]args){ Composite root = new Composite("服装"); Composite c1 = new Composite("男装"); Composite c2 = new Composite("女装"); Leaf leaf1 = new Leaf("衬衫"); Leaf leaf2 = new Leaf("夹克"); Leaf leaf3 = new Leaf("裙子"); Leaf leaf4 = new Leaf("套装"); root.addChild(c1); root.addChild(c2); c1.addChild(leaf1); c1.addChild(leaf2); c2.addChild(leaf3); c2.addChild(leaf4); root.printStruct(""); } }

能够看出,树枝构件类(Composite)给出了addChild()、removeChild()以及getChild()等方法的声明和实现,而树叶构件类则没有给出这些方法的声明或实现。这样的作法是安全的作法,因为这个特色,客户端应用程序不可能错误地调用树叶构件的汇集方法,由于树叶构件没有这些方法,调用会致使编译错误。

安全式合成模式的缺点是不够透明,由于树叶类和树枝类将具备不一样的接口。

透明式合成模式的结构

与安全式的合成模式不一样的是,透明式的合成模式要求全部的具体构件类,不论树枝构件仍是树叶构件,均符合一个固定接口。

源代码

抽象构件角色类

public abstract classComponent {

/*** 输出组建自身的名称 */ public abstract voidprintStruct(String preStr); /*** 汇集管理方法,增长一个子构件对象 * @paramchild 子构件对象 */ public voidaddChild(Component child){ /*** 缺省实现,抛出异常,由于叶子对象没有此功能 * 或者子组件没有实现这个功能 */ throw new UnsupportedOperationException("对象不支持此功能"); } /*** 汇集管理方法,删除一个子构件对象 * @paramindex 子构件对象的下标 */ public void removeChild(intindex){ /*** 缺省实现,抛出异常,由于叶子对象没有此功能 * 或者子组件没有实现这个功能 */ throw new UnsupportedOperationException("对象不支持此功能"); } /*** 汇集管理方法,返回全部子构件对象 */ public ListgetChild(){ /*** 缺省实现,抛出异常,由于叶子对象没有此功能 * 或者子组件没有实现这个功能 */ throw new UnsupportedOperationException("对象不支持此功能"); } }

树枝构件角色类,此类将implements Conponent改成extends Conponent,其余地方无变化。

public class Composite extendsComponent {

/*** 用来存储组合对象中包含的子组件对象 */ private List childComponents = new ArrayList(); /*** 组合对象的名字 */ privateString name; /*** 构造方法,传入组合对象的名字 * @paramname 组合对象的名字 */ publicComposite(String name){ this.name =name; } /*** 汇集管理方法,增长一个子构件对象 * @paramchild 子构件对象 */ public voidaddChild(Component child){ childComponents.add(child); } /*** 汇集管理方法,删除一个子构件对象 * @paramindex 子构件对象的下标 */ public void removeChild(intindex){ childComponents.remove(index); } /*** 汇集管理方法,返回全部子构件对象 */ public ListgetChild(){ returnchildComponents; } /*** 输出对象的自身结构 * @parampreStr 前缀,主要是按照层级拼接空格,实现向后缩进 */@Override public voidprintStruct(String preStr) { //先把本身输出 System.out.println(preStr + "+" + this.name); //若是还包含有子组件,那么就输出这些子组件对象 if(this.childComponents != null){ //添加两个空格,表示向后缩进两个空格 preStr += " "; //输出当前对象的子对象 for(Component c : childComponents){ //递归输出每一个子对象 c.printStruct(preStr); } } } }

树叶构件角色类,此类将implements Conponent改成extends Conponent,其余地方无变化。

public class Leaf extendsComponent {

/*** 叶子对象的名字 */ privateString name; /*** 构造方法,传入叶子对象的名称 * @paramname 叶子对象的名字 */ publicLeaf(String name){ this.name =name; } /*** 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字 * @parampreStr 前缀,主要是按照层级拼接的空格,实现向后缩进 */@Override public voidprintStruct(String preStr) { //TODO Auto-generated method stub System.out.println(preStr + "-" +name); } }

客户端类的主要变化是再也不区分Composite对象和Leaf对象。

public classClient {

public static voidmain(String[]args){ Component root = new Composite("服装"); Component c1 = new Composite("男装"); Component c2 = new Composite("女装"); Component leaf1 = new Leaf("衬衫"); Component leaf2 = new Leaf("夹克"); Component leaf3 = new Leaf("裙子"); Component leaf4 = new Leaf("套装"); root.addChild(c1); root.addChild(c2); c1.addChild(leaf1); c1.addChild(leaf2); c2.addChild(leaf3); c2.addChild(leaf4); root.printStruct(""); } }

能够看出,客户端无需再区分操做的是树枝对象(Composite)仍是树叶对象(Leaf)了;对于客户端而言,操做的都是Component对象。

两种实现方法的选择

这里所说的安全性合成模式是指:从客户端使用合成模式上看是否更安全,若是是安全的,那么就不会有发生误操做的可能,能访问的方法都是被支持的。

这里所说的透明性合成模式是指:从客户端使用合成模式上,是否须要区分究竟是“树枝对象”仍是“树叶对象”。若是是透明的,那就不用区分,对于客户而言,都是Compoent对象,具体的类型对于客户端而言是透明的,是无须关心的。

对于合成模式而言,在安全性和透明性上,会更看重透明性,毕竟合成模式的目的是:让客户端再也不区分操做的是树枝对象仍是树叶对象,而是以一个统一的方式来操做。

并且对于安全性的实现,须要区分是树枝对象仍是树叶对象。有时候,须要将对象进行类型转换,却发现类型信息丢失了,只好强行转换,这种类型转换必然是不够安全的。

所以在使用合成模式的时候,建议多采用透明性的实现方式。

java设计模式组合模式详解_《JAVA设计模式》之组合模式(Composite)相关推荐

  1. java get post 区别详解_[Java教程]GET 与 POST 其实没有什么区别

    [Java教程]GET 与 POST 其实没有什么区别 0 2020-12-30 11:36:20 GET 与 POST 其实没有什么区别 本文写于 2020 年 12 月 30 日 GET 与 PO ...

  2. java访问修饰符详解——学java,零基础不怕,不只要理论,更要实践+项目,a href=http://www.bjweixin.com太原维信科技提供 /a...

    java访问修饰符详解--学java,零基础不怕,不只要理论,更要实践+项目 <a href=http://www.bjweixin.com>太原维信科技提供 </a> pub ...

  3. Java高并发编程详解系列-Java线程入门

    根据自己学的知识加上从各个网站上收集的资料分享一下关于java高并发编程的知识点.对于代码示例会以Maven工程的形式分享到个人的GitHub上面.   首先介绍一下这个系列的东西是什么,这个系列自己 ...

  4. Solr系列二:solr-部署详解(solr两种部署模式介绍、独立服务器模式详解、SolrCloud分布式集群模式详解)...

    一.solr两种部署模式介绍 Standalone Server 独立服务器模式:适用于数据规模不大的场景 SolrCloud  分布式集群模式:适用于数据规模大,高可靠.高可用.高并发的场景 二.独 ...

  5. java编译器源码详解_已更新至第8章 | LLVM 编译框架详解

    LLVM是什么? 我又不做编译器研究,干嘛要管它? 这是一些朋友想要对LLVM发起的提问,那么今天我们就来看看那款据说很酷炫的编译器--LLVM. LLVM是什么? LLVM是一个自由软件项目,它是一 ...

  6. Java经典面试题详解:Java字符串转成list

    阿里巴巴Java岗面试题分享 1.HashMap 的内部结构?内部原理?和 HashTable 的区别,假如发⽣了 hash 碰撞,如何设计能让遍历效率⾼? 2.讲一讲讲讲 ConcurrentHas ...

  7. java策略模式详解_Java经典设计模式之策略模式原理与用法详解

    本文实例讲述了Java经典设计模式之策略模式.分享给大家供大家参考,具体如下: 策略模式指:策略模式指将程序中可变部分抽象分离成一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式 ...

  8. 设计模式之迭代器模式详解(JAVA 版)

    文章目录 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据. 关键代码:定义接口:hasNext, next ...

  9. Java高并发编程详解系列-Future设计模式

    导语   假设,在一个使用场景中有一个任务需要执行比较长的时间,通常需要等待任务执行结束之后或者是中途出错之后才能返回结果.在这个期间调用者只能等待,对于这个结果Future设计模式提供了一种凭据式的 ...

最新文章

  1. 学习java一定会用到的应用软件
  2. Redis基础学习(2)
  3. oracle服务端导出/导入方式expdp/impdp
  4. 玩转安卓10源码开发定制(17)编译Windows平台adb和fastboot工具
  5. 为oracle分配空间,ORACLE内存分配与调整(一)
  6. 基于高分辨率影像城市绿地信息提取_[转]ENVI支持下利用高分辨率影像城市绿地信息提取方案...
  7. java猫抓老鼠_猫抓老鼠-Java面向对象特点梳理
  8. opencv 入门笔记五 padding(图像加边框)
  9. 小技巧(1)「MacBook➕iPad」
  10. Java基础语法(汉罗塔)
  11. 将一坨很大数据保存为json,然后读取json。
  12. LUNA 黑天鹅事件:Terra CEO关于项目应急方案的社区AMA
  13. IE8 的开发人员工具 出不来了 怎么办?
  14. 矩阵之矩阵乘法(转载)
  15. 教你Java5分钟制作海报、彻底解决APP兼容性问题
  16. JavaScript事件的处理
  17. Apache ShardingSphere 4.0.0-RC2发布
  18. BaiduPCS-Go 下载文件出现 403 Forbidden 的解决方法
  19. 2021年山东省安全员C证考试内容及山东省安全员C证免费试题
  20. 快递分拣机器人应用的计算机知识,一种利用计算机控制的快递分拣机器人的制作方法...

热门文章

  1. 在C#中创建DataTable
  2. sigprocmask, sigpending, sigsuspend的用法
  3. python--批量下载豆瓣图片
  4. I00037 亏数(Deficient number)
  5. 配置java编译环境
  6. linux shell脚本备份mysql数据库
  7. JConsole的使用手册 JDK1.5(转)
  8. 西南大学校园GIS平台
  9. 【转】GitHub入门详细讲解
  10. Struts里面的配置笔记