组合模式定义:将对象组合成树形结构来表现“部分-整体”层次结构,组合模式使得用户以一致的方式处理单个对象以及组合对象
我们经常会遇到树状的对象关系,并且树的局部与整体有很高的相似性
北京总公司有下属人力资源部、财务部和办事处,上海华东分公司也有下属人力资源部、财务部和办事处,可见公司的整体组织架构和分公司的组织架构是一样的
如果按照对象的职能进行抽象,则会得到总公司、分公司、人力资源部、财务部以及办事处这几个类,如果公司较大,则不同职能的部门可能非常多,此时将抽象出过多的类,同时,由于公司业务的变动,相应的部门及部门的职能也可能发生变动,因此按照对象职能进行抽象不是一种很好的方式
由于局部整体间的相似性,可以抽取出父类并将公共方法放置其中,人力资源部、财务部及办事处是最小行政单元,并不能添加下级机构,总公司、分公司可以添加任意下级部门或分公司,我们按照能否添加下级机构抽象出两种不同的子类
package composite;
/**
* Created by seanzou on 2018/7/3.
*/
public abstract class Structure {
protected String name;
protected Integer level;
public Structure(String name, Integer level){
this.name = name;
this.level = level;
}
public void showStructure(){
StringBuilder builder = new StringBuilder();
for(int i = 1 ; i <= level ; i++)
if(level == i)
builder.append("|--");
else if(level > 1 && i == 1)
builder.append("| ");
else
builder.append(" ");
builder.append(name);
System.out.println(builder.toString());
}
}
package composite;
/**
* Created by seanzou on 2018/7/3.
*/
public class Department extends Structure {
public Department(String name, Integer level) {
super(name, level);
}
}
package composite;
import java.util.LinkedList;
import java.util.List;
/**
* Created by seanzou on 2018/7/3.
*/
public class Company extends Structure {
private List<Structure> childStructures = new LinkedList<>();
public Company(String name, Integer level) {
super(name, level);
}
public void add(Structure structure){
childStructures.add(structure);
}
public void remove(Structure structure){
childStructures.remove(structure);
}
@Override
public void showStructure(){
super.showStructure();
for(Structure structure : childStructures)
structure.showStructure();
}
}
package composite;
/**
* Created by seanzou on 2018/7/3.
*/
public class Client {
public static void main(String[] args){
Company bjCompany = new Company("BJ Company", 0);
Company shBranchCompany = new Company("SH Branch Company", 1);
Department bjHr = new Department("BJ Human Resource", 1);
Department bjFinance = new Department("BJ Finance", 1);
Department hnOffice = new Department("HN Office", 1);
bjCompany.add(shBranchCompany);
bjCompany.add(bjHr);
bjCompany.add(bjFinance);
bjCompany.add(hnOffice);
Department shHr = new Department("SH Human Resource", 2);
Department shFinance = new Department("SH Finance", 2);
Department njOffice = new Department("NJ Office", 2);
shBranchCompany.add(shHr);
shBranchCompany.add(shFinance);
shBranchCompany.add(njOffice);
bjCompany.showStructure();
}
}
执行结果如下:
BJ Company
|--SH Branch Company
| |--SH Human Resource
| |--SH Finance
| |--NJ Office
|--BJ Human Resource
|--BJ Finance
|--HN Office
此时再来看下组合模式的定义:组合模式使得用户以一致的方式处理单个对象以及组合对象
部门是最小行政单元,并不能添加下级机构,属于单个对象,公司可以添加任意下级部门或分公司,属于组合对象
部门与公司对外都提供showStructure方法,因此它们在对外展示组织架构这一层面是一致的
仅公司提供add及remove 方法,因此在搭建组织架构层面,部门与公司是不一致的
因此上面的设计仅提供局部一致性,并不能提供完整的对外一致性,来看看下面的设计
package composite;
/**
* Created by seanzou on 2018/7/3.
*/
public abstract class Structure {
protected String name;
protected Integer level;
public Structure(String name, Integer level){
this.name = name;
this.level = level;
}
public abstract void add(Structure structure);
public abstract void remove(Structure structure);
public void showStructure(){
StringBuilder builder = new StringBuilder();
for(int i = 1 ; i <= level ; i++)
if(level == i)
builder.append("|--");
else if(level > 1 && i == 1)
builder.append("| ");
else
builder.append(" ");
builder.append(name);
System.out.println(builder.toString());
}
}
package composite;
/**
* Created by seanzou on 2018/7/3.
*/
public class Department extends Structure {
public Department(String name, Integer level) {
super(name, level);
}
@Override
public void add(Structure structure) {
}
@Override
public void remove(Structure structure) {
}
}
package composite;
import java.util.LinkedList;
import java.util.List;
/**
* Created by seanzou on 2018/7/3.
*/
public class Company extends Structure {
private List<Structure> childStructures = new LinkedList<>();
public Company(String name, Integer level) {
super(name, level);
}
@Override
public void add(Structure structure){
childStructures.add(structure);
}
@Override
public void remove(Structure structure){
childStructures.remove(structure);
}
@Override
public void showStructure(){
super.showStructure();
for(Structure structure : childStructures)
structure.showStructure();
}
}
package composite;
/**
* Created by seanzou on 2018/7/3.
*/
public class Client {
public static void main(String[] args){
Structure bjCompany = new Company("BJ Company", 0);
Structure shBranchCompany = new Company("SH Branch Company", 1);
Structure bjHr = new Department("BJ Human Resource", 1);
Structure bjFinance = new Department("BJ Finance", 1);
Structure hnOffice = new Department("HN Office", 1);
bjCompany.add(shBranchCompany);
bjCompany.add(bjHr);
bjCompany.add(bjFinance);
bjCompany.add(hnOffice);
Structure shHr = new Department("SH Human Resource", 2);
Structure shFinance = new Department("SH Finance", 2);
Structure njOffice = new Department("NJ Office", 2);
shBranchCompany.add(shHr);
shBranchCompany.add(shFinance);
shBranchCompany.add(njOffice);
bjCompany.showStructure();
}
}
此时对于调用方来说,机构与公司不再有接口上的区别,因此我们可以修改代码,由依赖特定子类改为依赖共同父类,降低类之间的耦合度