组合模式

这是一个结构型模式,对象的结构模式描述了怎样把各种不同类型的对象组合在一起,以实现新功能的方法。可以在运行时刻改变对象组合关系,对象的结构模式是动态的。

面临问题

我们可以使用简单的对象组合成复杂的对象,而这个复杂对象有可以组合成更大的对象。我们可以把简单这些对象定义成类,然后定义一些容器类来存储这些简单对象。客户端代码必须区别对象简单对象和容器对象,而实际上大多数情况下用户认为它们是一样的。对这些类区别使用,使得程序更加复杂。递归使用的时候跟麻烦,而我们如何使用递归组合,使得用户不必对这些类进行区别呢?

也就是说,我们如何将“客户代码与复杂的对象容器结构”解耦?让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器?

解决方案:

将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

举个例子:文件系统由目录和文件组成。每个目录都可以装内容。目录的内容可以是文件,也可以是目录。按照这种方式,计算机的文件系统就是以递归结构来组织的。如果你想要描述这样的数据结构,那么你可以使用组合模式。这样,客户可以将对象的集合和个人的对象一视同仁。


注意上图中的leaf和composite都是通过继承实现的,这样保证了都是同样的类型。


组合模式的关键是定义了一个抽象构件类,它既可以代表叶子,又可以代表容器,而客户端针对该抽象构件类进行编程,无须知道它到底表示的是叶子还是容器,可以对其进行统一处理。
 同时容器对象与抽象构件类之间还建立一个聚合关联关系,在容器对象中既可以包含叶子,也可以包含容器,以此实现递归组合,形成一个树形结构。

 典型的Composite角色代码:
public class Composite extends Component
{
private ArrayList list = new ArrayList();//定义了一个list,用来存放子节点。因为其实composite实例化的对象是一个组合对象。
public void add(Component c)
{
list.add(c);//增加节点。
}
public void remove(Component c)
{
list.remove(c);//删除节点
}
public Component getChild(int i)
{
(Component)list.get(i);//获得组合对象的第几个节点。
}
public void operation()
{
for(Object obj:list)
{
((Component)obj).operation();//遍历所有孩子的所有操作,是个递归的过程。
}
} 
} 

应用举例:

一个绘图系统给出各种工具用来描绘由线、长方形和圆形等基本图形组成的图形。
 设计应当包括Line、Rectangle和Circle等对象,而且每一个对象都应当配备有一个draw()方法,在调用时会画出对象所代表的图形。
 由于一个复杂的图形是由基本图形组合而成的,因此,一个组合的图形应当有一个列表,存储对所有的基本图形对象的引用。复合图形的draw()方法在调用时,应当逐一调用所有列表上的基本图形对象的draw()方法。


相关的模式:

Decorator经常和Composite一起使用,通常有一个公共的父类
Flyweight可以共享组件但是不再能引用他们的父类对象
Iterator:可用来遍历Composite
Visitor:将本来应该分布在Composite和Leaf类中的操作和行为局部化


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值