组合模式(Composite),其含义是将对象组合成树形结构以表示”部分-整体“的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性,其用于解决对象访问接口不一致的问题。
在组合模式中有单个对象和复合对象之分,或者对象的结构是动态的并且复杂程度不一样,但客户需要一致地处理它们,这样就不难理解了。 对于复合对象也要像处单个元素一样来处理,降低与复杂对象的耦合性。
其适用性:
你想表示对象的部分-整体层次结构,
你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象
通常情况我们需要使Leaf和Composite类可以继承这个引用以及管理这个引用的那些操作,一个组合的所有子节点以这个组合为父节点,而反之该组合以这些节点为子节点,尽量要多定义一些公共操作。如下图:
Component类中定义了对象的各种操作,Composite类继承而来的复合对象的Add和Remove操作用于管理子部件,但对于Leaf类而言,如果企图向叶节点增加或者删除时会引入错误,这时最好使用缺省方式处理Add和Remove的失败。
在下例中,Employer类是抽象父类,其有两个子类Manager类和Programmer类,其中Programmer类是层次类中的叶节点,其不具有添加和删除功能,如:
Employer类中三个抽象方法,add,delete,getChild,于是组合对象Manager类实例中实现了这三个方法,而在Programmer类中企图进行这三个方法的调用均会抛出
UnsupportedOperationException("unsupported operation!") 异常。具体代码可参看本博客的github,下面是客户端测试Main.java:
package org.designpattern.structural.composite;
public static void main(String[] args){
Employer programmer = new Programmer();
Employer manager = new Manager();
Employer developer = new Programmer();
Employer architect = new Manager();
manager.add(architect);
manager.add(programmer);
manager.add(developer);
for(Employer e : manager.getFollowing()){
e.info();
}
System.out.println("------------------");
manager.delete(architect);
for(Employer e: manager.getFollowing()){
e.info();
}
System.out.println("-----------------");
for(int i = 0;i<manager.getFollowing().size();i++){
Employer employer = manager.getChild(i);
employer.info();
}
}
}
组合模式的缺点就是让设计变得更复杂了。但其采取树形方式使得对象一致地被处理,将客户代码和复杂对象机构,因此当需求中存在”部分-整体“问题时,不妨考虑组合模式解决一致性的问题。