组合模式:将对象组合成树形结构表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有统一性。
例子:一套办公系统,总公司的人力资源部以及财务部在分公司也要用,这其实就是整体和部分可以被一致对待的问题,这时可以用组合模式解决。
公司类:
public abstract class Company {
public String name;
public Company(String name) {
this.name = name;
}
/**
* 添加
* @param c
*/
public abstract void add(Company c);
/**
* 删除
* @param c
*/
public abstract void remove(Company c);
/**
* 显示
* @param depth
*/
public abstract void display(int depth);
/**
* 履行职责
*/
public abstract void lineOfDuty();
}
具体公司类:
public class ConcreteCompany extends Company {
private List<Company> children = new ArrayList<>();
public ConcreteCompany(String name) {
super(name);
}
@Override
public void add(Company c) {
children.add(c);
}
@Override
public void remove(Company c) {
children.remove(c);
}
@Override
public void display(int depth) {
System.out.println(depth + "--" + name);
for (Company component : children){
component.display(depth + 1);
}
}
@Override
public void lineOfDuty() {
for (Company company : children){
company.lineOfDuty();
}
}
}
人力资源部以及财务部:
public class HRDepartment extends Company {
public HRDepartment(String name) {
super(name);
}
@Override
public void add(Company c) {
}
@Override
public void remove(Company c) {
}
@Override
public void display(int depth) {
System.out.println(depth + "--" + name);
}
@Override
public void lineOfDuty() {
System.out.println(name + ": 招聘员工");
}
}
public class FinanceDepartment extends Company {
public FinanceDepartment(String name) {
super(name);
}
@Override
public void add(Company c) {
}
@Override
public void remove(Company c) {
}
@Override
public void display(int depth) {
System.out.println(depth + "--" + name);
}
@Override
public void lineOfDuty() {
System.out.println(name + ": 公司财务收支管理");
}
}
客户端代码:
public class ComponentTest {
public static void main(String[] args) {
ConcreteCompany root = new ConcreteCompany("上海总公司");
root.add(new HRDepartment("总公司人力资源部"));
root.add(new FinanceDepartment("总公司财务部"));
ConcreteCompany comp = new ConcreteCompany("北京分公司");
comp.add(new HRDepartment("北京分公司人力资源部"));
comp.add(new FinanceDepartment("北京分公司财务部"));
root.add(comp);
ConcreteCompany comp1 = new ConcreteCompany("南京办事处");
comp1.add(new HRDepartment("南京办事处人力资源部"));
comp1.add(new FinanceDepartment("南京办事处财务部"));
comp.add(comp1);
ConcreteCompany comp2 = new ConcreteCompany("杭州办事处");
comp2.add(new HRDepartment("杭州办事处人力资源部"));
comp2.add(new FinanceDepartment("杭州办事处财务部"));
comp.add(comp2);
System.out.println("结构图");
root.display(1);
System.out.println("职责");
root.lineOfDuty();
}
}
输出:
结构图
1--上海总公司
2--总公司人力资源部
2--总公司财务部
2--北京分公司
3--北京分公司人力资源部
3--北京分公司财务部
3--南京办事处
4--南京办事处人力资源部
4--南京办事处财务部
3--杭州办事处
4--杭州办事处人力资源部
4--杭州办事处财务部
职责
总公司人力资源部: 招聘员工
总公司财务部: 公司财务收支管理
北京分公司人力资源部: 招聘员工
北京分公司财务部: 公司财务收支管理
南京办事处人力资源部: 招聘员工
南京办事处财务部: 公司财务收支管理
杭州办事处人力资源部: 招聘员工
杭州办事处财务部: 公司财务收支管理
组合模式的好处
组合模式这样定义了包含人力资源部和财务部这些基本对象和分公司、办事处等组合对象的类层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户端代码中,任何用到基本对象的地方都可以使用组合对象了。
用户不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合写一些判断语句了。
简单来说,组合模式就是可以让客户一致性地使用组合结构和单个对象。
何时使用组合模式
需求中体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一使用组合结构中的所有对象时,就应该考虑使用组合模式。