1.组合模式的概念:
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性
2.组合模式的结构图
3.练习的例子
抽象公司类(结构图当中的Component):
/**
* 组合模式 抽象公司类
*/
@Data
abstract class Company {
private String name;
public Company(String name){
this.name = name;
}
/**
* 增加节点的方法
* @param company
*/
public abstract void add(Company company);
/**
* 移除节点的方法
* @param company
*/
public abstract void remove(Company company);
/**
* 展现树形结构
*/
public abstract void display(int path);
/**
* 公司中的各个部门履行职责
*
*/
public abstract void lineOfDuty();
/**
* 为了展现层级结构而做的方法
* @param path
* @return
*/
protected String getStr(int path) {
String str = "";
for (int i = 0; i <path ; i++) {
str += "-";
}
return str;
}
}
具体公司类(结构图当中的Compsite):
/**
* 具体公司类 (树枝节点)
*/
public class ConcreteCompany extends Company {
//定义一个保存树枝节点 树叶节点的聚集
private List<Company> arrayList = new ArrayList();
public ConcreteCompany(String name) {
super(name);
}
@Override
public void add(Company company) {
arrayList.add(company);
}
@Override
public void remove(Company company) {
arrayList.remove(company);
}
/**
* 遍历树
* @param path
*/
@Override
public void display(int path) {
System.out.println(getStr(path) + getName());
for (Company company:arrayList ) {
company.display(path + 2);
}
}
/**
* 让公司的树叶节(各个办事处)点履行职责
*/
@Override
public void lineOfDuty() {
for (Company company:arrayList ) {
company.lineOfDuty();
}
}
}
具体公司的人力资源部(结构图当中的leaf):
/**
* 公司的人力资源部(树叶节点)
*/
public class HRDepartment extends Company{
public HRDepartment(String name) {
super(name);
}
@Override
public void add(Company company) {}
@Override
public void remove(Company company) {}
@Override
public void display(int path) {
System.out.println(getStr(path) + getName());
}
@Override
public void lineOfDuty() {
System.out.println(getName() + ",招聘新员工!");
}
}
具体公司的财政部(结构图当中的leaf):
/**
* 财政部(树叶节点)
*/
public class FinanceDepartment extends Company{
public FinanceDepartment(String name) {
super(name);
}
@Override
public void add(Company company) {
}
@Override
public void remove(Company company) {
}
@Override
public void display(int path) {
System.out.println(getStr(path) + getName());
}
@Override
public void lineOfDuty() {
System.out.println(getName() + ",管理公司财政收支!");
}
}
测试类:
public class Test {
public static void main(String[] args) {
//树根
Company root = new ConcreteCompany("北京总公司");
root.add(new HRDepartment("总公司人力资源部"));
root.add(new FinanceDepartment("总公司财政部"));
Company company1 = new ConcreteCompany("上海分公司");
company1.add(new HRDepartment("上海分公司人力资源部"));
company1.add(new FinanceDepartment("上海分公司财政部"));
root.add(company1);
Company company2 = new ConcreteCompany("南京办事处");
company2.add(new HRDepartment("南京办事处人力资源部"));
company2.add(new FinanceDepartment("南京办事处出财政部"));
company1.add(company2);
Company company3 = new ConcreteCompany("杭州办事处");
company3.add(new HRDepartment("杭州办事处人力资源部"));
company3.add(new FinanceDepartment("杭州办事处出财政部"));
company1.add(company3);
//打印树的层级结构
root.display(1);
System.out.println();
//各个部门履行职责
root.lineOfDuty();
}
}
控制台:
4.例子的结构图
5.总结
组合方式有两种 上面的示例叫做 “透明模式” 操作子节点的方法声明在抽象的父类当中
- 问题:叶节点并不具备那些功能,所以实现是没有意义的
- 好处:叶节点和枝节点对于外界没有区别,他们具备完全一致的行为和接口
另外一种叫做“安全方式”,操作子节点的方法声明在Compsite类当中
- 问题:由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。
- 好处:这样叶节点就不用去实现那些无意义的方法了,避免了冗余
何时使用:当发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。
组合模式的好处:组合模式让用户可以一致的使用组合结构和单个对象