[Toc]java
树形结构在软件中随处可见,例如操做系统中的目录结构、应用软件中的菜单、办公系统中的公司组织结构等。git
组合模式经过一种巧妙的设计方案使得用户能够一致性地处理整个树形结构或者树形结构的一部分,也能够一致性地处理树形结构中的叶子节点(不包含子节点的节点)和容器节点(包含子节点的节点)。编程
组合模式(Composite Pattern):组合多个对象造成树形结构以表示具备“总体—部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具备一致性,组合模式又能够称为“总体—部分”(Part-Whole)模式,它是一种对象结构型模式。设计模式
在组合模式中引入了抽象构件类Component,它是全部容器类和叶子类的公共父类,客户端针对Component进行编程。组合模式结构如图所示:安全
代码实现了一个公司的组织架构,包括各级公司,各级公司包括各部门,AbstractOrganization充当抽象构建类,Company充当容器构建类(能够定义其余容器构建类),Department充当叶子构建类(能够定义其余叶子构建类)。架构
AbstractOrganizationide
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(); }
Companythis
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();
组合模式用户处理相似树形结构的包含容器对象和叶子对象的层次结构,经过该模式可忽略总体与部分的差别,让客户端统一对待它们,同时符合“开闭原则”利于扩展。