Java 设计模式 Composite

组合模式(Composite)属于结构性模式,它描述了对象间的组合关系。

对象间常常通过树结构来组织(包含)起来,以实现整体-部分的层次结构。整体上可以看做是一个组合对象

抛却各种复杂的术语,组合模式的特点是:

对象通过实现(继承)统一的接口(抽象类),调用者对单一对象和组合对象的操作具有一致性。

组合模式很常见,Java的容器类(比如ArrayList)都实现了组合模式。

 

我们平常操作最多的文件(夹)就是组合模式的最好例子。文件系统是树形层次结构,并且文件和文件夹提供给用户的一些操作是相同的,比如复制。于是,可以通过一个统一的接口将文件和文件夹统一起来,对用户提供一致的操作,屏蔽不同的复制实现过程。我们在复制文件夹的时候,操作系统实现了对文件夹内的所有文件和文件夹的复制,即实现了组合对象的整体复制,而不是一个空的文件夹;这和我们复制单个文件的体验是一致的。这便是组合模式的妙处.

 

通过实现组合模式,用户对文件夹的操作与对普通文件的操作并无差异。用户完全不用关心这是文件夹还是文件,也不用关心文件夹内部的具体结构,就可以完成相关操作。

同样的道理,我们可以表达如下:

通过实现组合模式,调用者对组合对象的操作与对单一对象的操作具有一致性。调用者不用关心这是组合对象还是文件,也不用关心组合对象内部的具体结构,就可以调用相关方法,实现功能。

如果从面向过程的角度思考,组合模式通过递归原理实现了树结构(组合对象)的深度优先遍历。

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

对象的树结构

一个树结构由两种节点组成:树枝节点和树叶节点。树枝节点可以有子节点,而一个树叶节点不可以有子节点。除了根节点外,其它节点有且只有一个父节点

 

角色细节:

  • 抽象构件(Component)角色:这是一个抽象角色,它给参与组合的对象规定一个接口。这个角色给出共有接口及其默认行为。
  • 树叶构件(Leaf)角色:代表参加组合的树叶对象。一个树叶对象没有下级子对象。
  • 树枝构件(Composite)角色:代表参加组合的有子对象的对象,并给出树枝构件对象的行为。
  • 可以看出,Composite类型的对象可以包含其它Component类型的对象。换而言之,Composite类型对象可以含有其它的树枝(Composite)类型或树叶(Leaf)类型的对象。

    合成模式的实现根据所实现接口的区别分为两种形式,分别称为安全模式和透明模式。合成模式可以不提供父对象的管理方法,但合成模式必须在合适的地方提供子对象的管理方法(诸如:add、remove、getChild等)。

    透明方式

    作为第一种选择,在Component里面声明所有的用来管理子类对象的方法,包括add()、remove(),以及getChild()方法。 这样做的好处是所有的构件类都有相同的接口。在客户端看来,树叶类对象与合成类对象的区别起码在接口层次上消失了,客户端可以同等同的对待所有的对象。这 就是透明形式的合成模式。

    这个选择的缺点是不够安全,因为树叶类对象和合成类对象在本质上是有区别的。树叶类对象不可能有下一个层次的对象,因此add()、remove()以及getChild()方法没有意义,是在编译时期不会出错,而只会在运行时期才会出错。

    安全方式

    第二种选择是在Composite类里面声明所有的用来管理子类对象的方法。这样的做法是安全的做法,因为树叶类型的对象根本就没有管理子类对象的方法,因此,如果客户端对树叶类对象使用这些方法时,程序会在编译时期出错。

    这个选择的缺点是不够透明,因为树叶类和合成类将具有不同的接口。

    这两个形式各有优缺点,需要根据软件的具体情况做出取舍决定。

     

    使用合成模式时考虑的几个问题
    1.明显的给出父对象的引用。在子对象里面给出父对象的引用,可以很容易的遍历所有父对象。有了这个引用,可以方便的应用责任链模式。
    2.在通常的系统里,可以使用享元模式实现构件的共享,但是由于合成模式的对象经常要有对父对象的引用,因此共享不容易实现。
    3.有时候系统需要遍历一个树枝结构的子构件很多次,这时候可以考虑把遍历子构件的结果暂时存储在父构件里面作为缓存。
    4.关于使用什么数据类型来存储子对象的问题,在示意性的代码中使用了ArrayList,在实际系统中可以使用其它聚集或数组等。
    5.客户端尽量不要直接调用树叶类中的方法,而是借助其父类(Component)的多态性完成调用,这样可以增加代码的复用性


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xmouse/archive/2008/04/11/2281920.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值