1 定义
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的适用具有一致性,即整体和部分可以被一致对待。
2 透明方式和安全方式
两者各有好处,视情况而定选哪种。
- 透明方式:Compoment抽象类中声明了用来管理子类的方法,包括add(), remove()等,这样继承了该抽象类的类都具有add(), remove()方法。
好处:
叶节点和枝节点对于外界没有区别,具备一致的行为接口。缺点:
Leaf类本身不具备add(), remove()方法的功能,所以实现它是没有意义的。 - 安全方式:Compoment抽象类中不声明add(), remove(),Leaf类就不用实现这2个方法,而是在Composite中声明用来管理子类对象的方法。
好处:
不会出现上面的问题。缺点:
树叶和树枝类不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。
3 适用场景
- 需求中是体现部分与整体层次的结构时;
- 希望用户可以忽略组合对象和单个对象的不同,统一的使用组合结构中的所有对象时;
满足以上两点,则应该考虑 使用组合模式。
4 优势
- 组合模式定义了包含基本对象和组合对象的层次结构。基本对象可以被组合成更复杂的组合对象,这个组合对象又可以被组合,这样不断地递归下去,
客户代码中,任何使用到基本对象的地方都可以使用组合对象了
。 - 让客户可以一致的使用组合结构和单个对象。
5 UML图
6 例子
6.1 场景
北京总公司下面有很多直属部门和分公司。不管是直属部门还是分公司下面的小部门,只要他们是同一类型的部门,比如都是财务部,就应该有一样的功能职责。公司层次结构图如下:
6.2 UML图
6.3 code
Main
public class Main {
public static void main(String[] args) {
ConcreteCompany company=new ConcreteCompany("总公司");
FinanceDepartment financeDepartment=new FinanceDepartment("总公司财务部");
HRDepartment hrDepartment=new HRDepartment("总公司人力资源部");
company.add(financeDepartment);
company.add(hrDepartment);
//一级分公司
ConcreteCompany subCmp1=new ConcreteCompany("上海华东分公司");
FinanceDepartment financeDepartment1=new FinanceDepartment("上海华东分公司财务部");
HRDepartment hrDepartment1=new HRDepartment("上海华东分公司人力资源部");
subCmp1.add(financeDepartment1);
subCmp1.add(hrDepartment1);
company.add(subCmp1);
//二级分公司
ConcreteCompany subCmp2=new ConcreteCompany("南京办事处");
FinanceDepartment financeDepartment2=new FinanceDepartment("南京办事处财务部");
HRDepartment hrDepartment2=new HRDepartment("南京办事处人力资源部");
subCmp2.add(financeDepartment2);
subCmp2.add(hrDepartment2);
subCmp1.add(subCmp2);
//二级分公司
ConcreteCompany subCmp3=new ConcreteCompany("杭州办事处");
FinanceDepartment financeDepartment3=new FinanceDepartment("杭州办事处财务部");
HRDepartment hrDepartment3=new HRDepartment("杭州办事处人力资源部");
subCmp3.add(financeDepartment3);
subCmp3.add(hrDepartment3);
subCmp1.add(subCmp3);
//展示公司层级结构
System.out.println("公司层级结构如下:");
company.display(1);
//展示各个部门职责
System.out.println("各个部门职责如下:");
company.lineOfDuty();
}
}
Company
public abstract class Company {
protected String name;
public Company(String name){
//注意这里要写上this哦,不然就成了:参数=参数,类属性并未赋值,依然是null
this.name=name;
}
public abstract void add(Company c);//增加
public abstract void remove(Company c);//移除
public abstract void display(int depth);//显示
public abstract void lineOfDuty();//履行职责
}
ConcreteCompany
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) {
StringBuilder sb=new StringBuilder();
while (depth--!=0){
sb.append("-");
}
System.out.println(sb.toString()+name);
for (Company c:children) {
c.display(depth+2);
}
}
@Override
public void lineOfDuty() {
for (Company c:children) {
c.lineOfDuty();
}
}
}
HRDepartment
//人力资源部门
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) {
StringBuilder sb=new StringBuilder();
while (depth--!=0){
sb.append("-");
}
System.out.println(sb.toString()+name);
}
@Override
public void lineOfDuty() {
System.out.println(String.format("%s员工招聘培训管理",name));
}
}
FinanceDepartment
//财务部门
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) {
StringBuilder sb=new StringBuilder();
while (depth--!=0){
sb.append("-");
}
System.out.println(sb.toString()+name);
}
@Override
public void lineOfDuty() {
System.out.println(String.format("%s公司财务收支管理",name));
}
}
参考
https://blog.csdn.net/caoxiaohong1005/article/details/79155028