顿搜
组合模式(Composite)——23种设计模式之结构型模式
在面向对象的系统中,我们常会遇到一类具有 “容器”特征的对象-->它们在充当对象的同时, 又是其他对象的容器。如果我们要对这样的对象容器进行处理,将面 临比较复杂的递归过程。
客户代码过多地依赖于对象容器复杂的内部实现结构, 对象容器内部实现结构(而非抽象接口)的变化将引起 客户代码的频繁变化,带来了代码的维护性、扩展性 差等问题。
如何将“客户代码与复杂的对象容器结构”解耦?让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器?
如果一些部件对象经过组合构成的复合部件对象仍然具有 单个部件对象的接口,这样的复合部件对象被称为 “容器(container)”。复合部件与单个部件具有同样的接口,所有接口包含两部分:单个部件的功能、管理子部件的功能,这样的结构具有递归组合特点,在这种场景下,我们引入“组合模式”来解决“客户端代码与复杂的对象容器结构”解耦的问题。
一、类图表示
组合模式涉及到Component (抽象构件类),Leaf (叶子),Composite (容器对象),Client(客户端)等四个角色
- ①、Leaf (叶子):在组合中表示叶节点对象,没有子节点,在组合中定义图元对象的行为
- ②、Composite (容器对象):定义有子部件的那些部件的行为,存储子部件,在Component接口中实现与子部件有关的操作
- ③、Client(客户端):通过Component接口操纵组合部件的对象
- ④、Component (抽象构件类):为组合中的对象声明接口,在适当的情况下实现所有类共有接口的缺省行为,声明一个接口用于访问和管理Component的子组件,(可选)在递归结构中定义一个接口,用于访问一个父部件,并在 合适的情况下实现它。
1、安全组合模式
只有容器构件角色才配备管理聚集的方法,而叶子构 件没有这些方法
2、透明式组合模式
容器构件和叶子构件角色都配备管理聚集的方法。
二、代码示例
public interface Component {
public void operation();
public boolean add(Component o);
public boolean remove(Component o);
public List getChildren();
}public class Composite implements Component {
private String name;
private List children = new ArrayList();
public Composite(String name){
this.name = name;
}
public void operation(){
System.out.println(name);
}
public boolean add(Component o){
if(!children.contains(o)){
children.add(o);
}
return true;
}
public boolean remove(Component o){
children.remove(o);
return true;
}
public List getChildren(){
return children;
}
}public class Leaf implements Component {
private String name;
public Leaf(String name){
this.name = name;
}
public void operation(){
System.out.println(name);
}
public boolean add(Component o){
return false;
}
public boolean remove(Component o){
return false;
}
public List getChildren(){
return null;
}
}public class Client {
private static void doCircle(Component o){
List list = o.getChildren();
if(list!=null && list.size()>0){
for(int i=0;i<list.size();i++){
Component sub = (Component)list.get(i);
sub.operation();
//递归执行
doCircle(sub);
}
}
}
public static void main(String[] args) {
Component root = new Composite("树干");
Component comp1 = new Composite("树枝一");
Component comp2 = new Composite("树枝二");
root.add(comp1);
root.add(comp2);
Component leaf1 = new Leaf("叶一");
Component leaf2 = new Leaf("叶二");
comp1.add(leaf1);
comp1.add(leaf2);
doCircle(root);
}
}三、优缺点分析
1、优点
- ①、定义了包含leaf对象和composite对象的类层次接口—— 递归结构
- ②、简化客户代码,因为客户端不需要知道构件是叶子还是容器对象,客户一致地处理复合对象和单个对象
- ③、使得更容易增加新类型的组件,易于增加新类型的组件
- ④、使设计变得更加一般化,无法限制类型的组合,可以在运行时刻通过类型检查加以弥补
2、缺点
- ①、使用组合模式后,控制容器对象的类型就不太容易。
- ②、用继承的方法增加新的行为很困难。
四、与其它模式的关系
1、与装饰者模式关系
- ①、Decorator经常和Composite一起使用,通常有一个 公共的父类
2、与享元模式的关系
- ①、Flyweight可以共享组件但是不再能引用他们的父类对象
3、与迭代器模式的关系
- ①、Iterator:可用来遍历Composite
4、与访问者模式的关系
- ①、Visitor:将本来应该分布在Composite和Leaf类中的操作和行为局部化
五、总结
组合模式是很多复杂模式的一部分
- ①、组合模式的关键是定义了一个抽象构件类, 它既可以代表叶子,又可以代表容器,而客 户端针对该抽象构件类进行编程,无须知道 它到底表示的是叶子还是容器,可以对其进 行统一处理。
- ②、同时容器对象与抽象构件类之间还建立一个 聚合关联关系,在容器对象中既可以包含叶 子,也可以包含容器,以此实现递归组合, 形成一个树形结构。

