组合模式(Composite Pattern),又叫部分整体模式,属于结构型设计模式,它主要用于将一组相似的对象作为一个单一对象来看待,再依据树形结构来组合对象,用来表示部分以及整体层次,使得调用者可以使用一致的方法操作单个对象或组合对象。例如现实场景中,一个公司里面包含了人事部、技术部、业务部和分公司等,而分公司里的组织结构也同样具有人事部、技术部、业务部等部门。总公司部门和分公司部门都可以理解为属于公司统一管理,是公司的部门或叫旗下部门,这其实就是整体与部分可以被一致对待的表现。
组合模式一般包含3个角色,分别是:
在实现方式上,组合模式可分为透明方式和安全方式,它们的主要区别在于组合部件中:
组合部件类,它是公司的统称和对象共同行为、子对象增加删除行为的定义:
public abstract class Company {
protected String mName;
public Company(String name) {
mName = name;
}
public abstract void action();
public abstract void add(Company company);
public abstract void remove(Company company);
}
叶子节点类,它继承于组合部件类,是具体的部门:
public class TechnologyDepartment extends Company {
public TechnologyDepartment(String name) {
super(name);
}
@Override
public void action() {
System.out.println("我是" + mName + "负责技术攻关");
}
@Override
public void add(Company company) {
}
@Override
public void remove(Company company) {
}
}
public class SalesDepartment extends Company {
public SalesDepartment(String name) {
super(name);
}
@Override
public void action() {
System.out.println("我是" + mName + "负责业务工作");
}
@Override
public void add(Company company) {
}
@Override
public void remove(Company company) {
}
}
合成部件类,它也继承于组合部件类,它可以是总公司,也可以是分公司:
public class ConcreteCompany extends Company {
private List mCompaynList = new ArrayList<>();
public ConcreteCompany(String name) {
super(name);
}
@Override
public void action() {
for (Company company: mCompaynList) {
company.action();
}
}
@Override
public void add(Company company) {
mCompaynList.add(company);
}
@Override
public void remove(Company company) {
mCompaynList.remove(company);
}
}
客户端:
Company rootCompany = new ConcreteCompany("总公司");
rootCompany.add(new TechnologyDepartment("总公司技术部"));
rootCompany.add(new SalesDepartment("总公司销售部"));
Company branchCompany = new ConcreteCompany("分公司");
branchCompany.add(new TechnologyDepartment("分公司技术部"));
branchCompany.add(new SalesDepartment("分公司销售部"));
rootCompany.add(branchCompany);
rootCompany.action();
输出结果:
我是总公司技术部负责技术攻关
我是总公司销售部负责业务工作
我是分公司技术部负责技术攻关
我是分公司销售部负责业务工作
组合部件类,它是公司的统称,这里仅声明对象共同行为:
public abstract class Company {
protected String mName;
public Company(String name) {
mName = name;
}
protected abstract void action();
}
单独声明子对象增加删除行为的定义的接口:
public interface INode {
void add(Company company);
void remove(Company company);
}
叶子节点类,它继承于组合部件类,是具体的部门:
public class TechnologyDepartment extends Company {
public TechnologyDepartment(String name) {
super(name);
}
@Override
protected void action() {
System.out.println("我是" + mName + "负责技术攻关");
}
}
public class SalesDepartment extends Company {
public SalesDepartment(String name) {
super(name);
}
@Override
protected void action() {
System.out.println("我是" + mName + "负责业务工作");
}
}
合成部件类,它也继承于组合部件类,它可以是总公司,也可以是分公司:
public class ConcreteCompany extends Company implements INode {
private List mCompaynList = new ArrayList<>();
public ConcreteCompany(String name) {
super(name);
}
@Override
public void add(Company company) {
mCompaynList.add(company);
}
@Override
public void remove(Company company) {
mCompaynList.remove(company);
}
@Override
public void action() {
for (Company company: mCompaynList) {
company.action();
}
}
}
客户端:
ConcreteCompany rootCompany = new ConcreteCompany("总公司");
rootCompany.add(new TechnologyDepartment("总公司技术部"));
rootCompany.add(new SalesDepartment("总公司销售部"));
ConcreteCompany branchCompany = new ConcreteCompany("分公司");
branchCompany.add(new TechnologyDepartment("分公司技术部"));
branchCompany.add(new SalesDepartment("分公司销售部"));
rootCompany.add(branchCompany);
rootCompany.action();
输出结果:
我是总公司技术部负责技术攻关
我是总公司销售部负责业务工作
我是分公司技术部负责技术攻关
我是分公司销售部负责业务工作
组合模式就是让调用者可以一致地使用组合结构和单个对象。在需求中体现部分与整体层次结构时,以及希望调用者可以忽略组合对象与单个对象的不同,统一使用组合结构中的所有对象时就应该考虑使用组合模式。它可以让调用者无需关心处理的对象是单个还是容器,当有新的部件时很容易就可添加进来,但同时也使对象关系复杂化,调用者需花更多时间来理解类之间的层次关系。