我们先了解一下组合模式吧!组合模式指的是对象的组合,组合模式可以以树状形式来描述对象与对象的一组孩子之间的层次关系,运用组合模式,可以让个体以及个体下的组合(一组对象) 都使用同样的编程模型!也就是说,如果用了组合模式,无论是枝干节点还是叶子节点,我们都可用在上面调用一样的方法,我们不用去关心它到底是枝干还是叶子,从而达到对客户端的透明性;
假设现在你要为某个集团设计一个代码结构,可以展示他们的全部公司,母公司,子公司,子公司的子公司...这种数据结构完全就是一颗树形,他们希望的是,无论是母公司还是子公司,对客户端而言是透明的,他不去关心该公司在树形中的位置,他只知道调用通用的方法;
这些公司的关系图如下所示:
OK,要想达到这样的效果,可以肯定的是,母公司和子公司都得有共同的父类; 在组合模式中,这个父类我们称之为抽象组件;而每一个实现它的类都是一个组件;
/**抽象公司组件*/
abstract class AbstractCompanyCompoment{
//公司名称
protected String name ;
protected List<AbstractCompanyCompoment> acList = new ArrayList<AbstractCompanyCompoment>();;
//添加组件
abstract void addCompanyCompoment(AbstractCompanyCompoment abstractCompanyCompoment);
//移除组件
abstract void removeCompanyCompoment(AbstractCompanyCompoment abstractCompanyCompoment);
//打印公司名称,为节省代码,直接定义在父类中!
protected void print(){
System.out.println(this.name);
for (AbstractCompanyCompoment ac : acList) {
ac.print();
}
}
}
接下来我们来创建4个公司:
/**母公司*/
class ParentCompany extends AbstractCompanyCompoment{
public ParentCompany() {
this.name = "母公司";
}
@Override
void addCompanyCompoment(AbstractCompanyCompoment abstractCompanyCompoment) {
this.acList.add(abstractCompanyCompoment);
}
@Override
void removeCompanyCompoment(
AbstractCompanyCompoment abstractCompanyCompoment) {
if(this.acList.contains(abstractCompanyCompoment)){
this.acList.remove(abstractCompanyCompoment);
}
}
}
/**子公司1*/
class ChildCompanyOne extends AbstractCompanyCompoment{
public ChildCompanyOne() {
this.name = "子公司1";
}
@Override
void addCompanyCompoment(AbstractCompanyCompoment abstractCompanyCompoment) {
this.acList.add(abstractCompanyCompoment);
}
@Override
void removeCompanyCompoment(
AbstractCompanyCompoment abstractCompanyCompoment) {
if(this.acList.contains(abstractCompanyCompoment)){
this.acList.remove(abstractCompanyCompoment);
}
}
}
/**子公司1-1*/
class ChildCompanyOneToOne extends AbstractCompanyCompoment{
public ChildCompanyOneToOne() {
this.name = "子公司1-1";
}
@Override
void addCompanyCompoment(AbstractCompanyCompoment abstractCompanyCompoment) {
this.acList.add(abstractCompanyCompoment);
}
@Override
void removeCompanyCompoment(
AbstractCompanyCompoment abstractCompanyCompoment) {
if(this.acList.contains(abstractCompanyCompoment)){
this.acList.remove(abstractCompanyCompoment);
}
}
}
/**子公司1-2*/
class ChildCompanyOneToTwo extends AbstractCompanyCompoment{
public ChildCompanyOneToTwo() {
this.name = "子公司1-2";
}
@Override
void addCompanyCompoment(AbstractCompanyCompoment abstractCompanyCompoment) {
this.acList.add(abstractCompanyCompoment);
}
@Override
void removeCompanyCompoment(
AbstractCompanyCompoment abstractCompanyCompoment) {
if(this.acList.contains(abstractCompanyCompoment)){
this.acList.remove(abstractCompanyCompoment);
}
}
}
/**子公司2*/
class ChildCompanyTwo extends AbstractCompanyCompoment{
public ChildCompanyTwo() {
this.name = "子公司2";
}
@Override
void addCompanyCompoment(AbstractCompanyCompoment abstractCompanyCompoment) {
this.acList.add(abstractCompanyCompoment);
}
@Override
void removeCompanyCompoment(
AbstractCompanyCompoment abstractCompanyCompoment) {
if(this.acList.contains(abstractCompanyCompoment)){
this.acList.remove(abstractCompanyCompoment);
}
}
}
public class Test {
public static void main(String[] args) {
AbstractCompanyCompoment parent = new ParentCompany();
AbstractCompanyCompoment childOne = new ChildCompanyOne();
childOne.addCompanyCompoment(new ChildCompanyOneToOne());
childOne.addCompanyCompoment(new ChildCompanyOneToTwo());
parent.addCompanyCompoment(childOne);
AbstractCompanyCompoment childTwo = new ChildCompanyTwo();
parent.addCompanyCompoment(childTwo);
parent.print();
System.out.println("*****************************");
childOne.print();
System.out.println("*****************************");
childTwo.print();
}
}
*********************************************************************************
母公司
子公司1
子公司1-1
子公司1-2
子公司2
*****************************
子公司1
子公司1-1
子公司1-2
*****************************
子公司2
*********************************************************************************
在测试类中我们看到,无论是对于根节点还是叶子节点,我们都直接调用它的print()方法使其打印它的名字,对我们使用者而言,根本不去关心它的层级,只要调用了print方法,相关的公司组件就会做正确的事情,比如它会继续叫自己的下级打印名字;