本文共 4195 字,大约阅读时间需要 13 分钟。
组合模式(Composite),也称为 整体-部分(Part-Whole)模式,它的宗旨是通过将单个对象(叶子节点)和组合对象(树枝节点)用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性。
一般用来描述 整体 与 部分 的关系,它将对象组织到树形结构中,最顶层的节点称为 根节点,根节点下面可以包含 树枝节点 和 叶子节点,树枝节点下面又可以包含 树枝节点 和 叶子节点。如下图所示:
由上图可以看出,其实 根节点 和 树枝节点 本质上是同一种数据类型(蓝色圆圈),可以作为容器使用;而 叶子节点 与 树枝节点 在语义上不属于同一种类型,但是在 中,会把 树枝节点 和 叶子节点 认为是同一种数据类型(用同一接口定义),让它们具备一致行为。这样,在 中,整个树形结构中的对象都是同一种类型,带来的一个好处就是客户无需辨别 树枝节点 还是 叶子节点,而是可以直接进行操作,给客户使用带来极大的便利。
核心:借助同一接口,使叶子节点和树枝节点的操作具备一致性。
当子系统与其内各个对象层次呈现树形结构时,可以使用 让该子系统内各个对象层次的行为操作具备一致性。客户端使用该子系统内任意一个层次对象时,无须进行区分,直接使用通用操作即可,为客户端的使用带来了便捷。
注:如果树形结构系统不使用 进行架构,那么按照正常的思维逻辑,对该系统进行职责分析,按上文树形结构图所示,该系统具备两种对象层次类型:树枝节点和叶子节点。那么我们就需要构造两种对应的类型,然后由于树枝节点具备容器功能,因此树枝节点类内部需维护多个集合存储其他对象层次(eg:List<Composite>
,List<Leaf>
),如果当前系统对象层次更复杂时,那么树枝节点内就又要增加对应的层次集合,这对树枝节点的构建带来了巨大的复杂性,臃肿性以及不可扩展性。同时客户端访问该系统层次时,还需进行层次区分,这样才能使用对应的行为,给客户端的使用也带来了巨大的复杂性。而如果使用 构建该系统,由于 抽取了系统各个层次的共性行为,具体层次只需按需实现所需行为即可,这样子系统各个层次就都属于同一种类型,所以树枝节点只需维护一个集合(List<Component>
)即可存储系统所有层次内容,并且客户端也无需区分该系统各个层次对象,对内系统架构简洁优雅,对外接口精简易用。
优点
缺点
主要包含三种角色:
1、公司类(抽象类或接口),component
public abstract class Company { private String name; public Company(String name) { this.name = name; } public abstract void add(Company company); public abstract void remove(Company company); public abstract void display(int depth);}
2、具体公司类(树枝节点)
public class ConcreteCompany extends Company { private ListchildreList = new ArrayList<>(); private String name; public ConcreteCompany(String name) { super(name); this.name = name; } @Override public void add(Company company) { childreList.add(company); } @Override public void remove(Company company) { childreList.remove(company); } @Override public void display(int depth) { StringBuilder stringBuilder = new StringBuilder(); for (int i=0;i
3、人力部(叶节点)
private String name; public HRDepartment(String name) { super(name); this.name = name; } @Override public void add(Company company) { } @Override public void remove(Company company) { } @Override public void display(int depth) { StringBuilder stringBuilder = new StringBuilder(); for (int i=0;i
4、财务部(叶节点)
public class FinanceDepartment extends Company { private String name; public FinanceDepartment(String name) { super(name); this.name = name; } @Override public void add(Company company) { } @Override public void remove(Company company) { } @Override public void display(int depth) { StringBuilder stringBuilder = new StringBuilder(); for (int i=0;i
5、测试类
public class Test { public static void main(String[] args) { ConcreteCompany root = new ConcreteCompany("北京总公司"); root.add(new HRDepartment("总公司人力资源部")); root.add(new FinanceDepartment("总公司财务部")); ConcreteCompany composite = new ConcreteCompany("上海华东分公司"); composite.add(new HRDepartment("华东分公司人力资源部")); composite.add(new FinanceDepartment("华东分公司财务部")); root.add(composite); ConcreteCompany composite1 = new ConcreteCompany("南京办事处"); composite1.add(new HRDepartment("南京办事处人力资源部")); composite1.add(new FinanceDepartment("南京办事处财务部")); composite.add(composite1); ConcreteCompany composite2 = new ConcreteCompany("杭州办事处"); composite2.add(new HRDepartment("杭州办事处人力资源部")); composite2.add(new FinanceDepartment("杭州办事处财务部")); composite.add(composite2); System.out.println("结构图:"); root.display(1); }}输出:- 北京总公司- - - 总公司人力资源部- - - 总公司财务部- - - 上海华东分公司- - - - - 华东分公司人力资源部- - - - - 华东分公司财务部- - - - - 南京办事处- - - - - - - 南京办事处人力资源部- - - - - - - 南京办事处财务部- - - - - 杭州办事处- - - - - - - 杭州办事处人力资源部- - - - - - - 杭州办事处财务部
注:参考文献《大话设计模式》程杰著。