目录
树形结构在软件中随处可见,例如操作系统中的目录结构、应用软件中的菜单、办公系统中的公司组织结构等。
组合模式通过一种巧妙的设计方案使得用户可以一致性地处理整个树形结构或者树形结构的一部分,也可以一致性地处理树形结构中的叶子节点(不包含子节点的节点)和容器节点(包含子节点的节点)。
组合模式(Composite Pattern):组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“整体—部分”(Part-Whole)模式,它是一种对象结构型模式。
在组合模式中引入了抽象构件类Component,它是所有容器类和叶子类的公共父类,客户端针对Component进行编程。组合模式结构如图所示:

代码实现了一个公司的组织架构,包括各级公司,各级公司包括各部门,AbstractOrganization充当抽象构建类,Company充当容器构建类(可以定义其他容器构建类),Department充当叶子构建类(可以定义其他叶子构建类)。
AbstractOrganization
public abstract class AbstractOrganization {
    public abstract void add(AbstractOrganization organization);
    public abstract void remove(AbstractOrganization organization);
    public abstract  AbstractOrganization getChild(int i);
    public abstract void notifyMessage();
}Company
public class Company extends AbstractOrganization {
    private List<AbstractOrganization> organizationList=new ArrayList<>();
    private String name;
    public Company(String name) {
        this.name = name;
    }
    @Override
    public void add(AbstractOrganization organization) {
        organizationList.add(organization);
    }
    @Override
    public void remove(AbstractOrganization organization) {
        organization.remove(organization);
    }
    @Override
    public AbstractOrganization getChild(int i) {
        return organizationList.get(i);
    }
    @Override
    public void notifyMessage() {
        System.out.println("对公司:"+name+" 进行通知");
        for (AbstractOrganization organization:organizationList){
            organization.notifyMessage();
        }
    }
}Department
public class Department extends AbstractOrganization {
    private String name;
    public Department(String name) {
        this.name = name;
    }
    @Override
    public void add(AbstractOrganization organization) {
        System.out.println("对不起,不支持该方法!");
    }
    @Override
    public void remove(AbstractOrganization organization) {
        System.out.println("对不起,不支持该方法!");
    }
    @Override
    public AbstractOrganization getChild(int i) {
        System.out.println("对不起,不支持该方法!");
        return null;
    }
    @Override
    public void notifyMessage() {
        System.out.println("对"+name+" 进行通知");
    }
}Client
public class Client {
    public static void main(String[] args) {
        AbstractOrganization c1,c2,d1,d2,d3;
        c1=new Company("总公司");
        c2=new Company("分公司1");
        d1=new Department("总公司部门1");
        d2=new Department("分公司部门1");
        d3=new Department("分公司部门2");
        c1.add(c2);
        c1.add(d1);
        c2.add(d2);
        c2.add(d3);
        //客户端无序关心节点的层次结构,对节点可以进行统一处理
        c1.notifyMessage();
        System.out.println("-------------");
        c2.notifyMessage();
    }
}
//对公司:总公司 进行通知
//对公司:分公司1 进行通知
//对分公司部门1 进行通知
//对分公司部门2 进行通知
//对总公司部门1 进行通知
//-------------
//对公司:分公司1 进行通知
//对分公司部门1 进行通知
//对分公司部门2 进行通知透明组合模式中,抽象构件Component中声明了所有用于管理成员对象的方法,包括add()、remove()以及getChild()等方法,这样做的好处是确保所有的构件类都有相同的接口。在客户端看来,叶子对象与容器对象所提供的方法是一致的,客户端可以相同地对待所有的对象。
透明组合模式的缺点是不够安全,因为叶子对象和容器对象在本质上是有区别的。叶子对象不可能有下一个层次的对象,即不可能包含成员对象,因此为其提供add()、remove()以及getChild()等方法是没有意义的,这在编译阶段不会出错,但在运行阶段如果调用这些方法可能会出错(如果没有提供相应的错误处理代码)。
Java AWT中使用的组合模式就是安全组合模式。
安全组合模式中,在抽象构件Component中没有声明任何用于管理成员对象的方法,而是在Composite类中声明并实现这些方法。这种做法是安全的,因为根本不向叶子对象提供这些管理成员对象的方法,对于叶子对象,客户端不可能调用到这些方法。
安全组合模式的缺点是不够透明,因为叶子构件和容器构件具有不同的方法,且容器构件中那些用于管理成员对象的方法没有在抽象构件类中定义,因此客户端不能完全针对抽象编程,必须有区别地对待叶子构件和容器构件。
客户端需要指定具体的容器类型,才能调用管理成员对象的方法。
Comapany c1,c2;
AbstractOrganization d1,d2,d3;
...
c1.notifyMessage();组合模式用户处理类似树形结构的包含容器对象和叶子对象的层次结构,通过该模式可忽略整体与部分的差异,让客户端统一对待它们,同时符合“开闭原则”利于扩展。
原文:https://www.cnblogs.com/ading-blog/p/9678293.html