组合模式的基本介绍
- 组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的层次关系。
- 这种类型的设计模式属于结构型模式。
- 组合模式使得用户对单个对象和组合对象的访问具有一致性,即:组合能让客户以一致的方式处理个别对象以及组合对象
组合模式的通用类图

我们先来说说组合模式的几个角色:
- 抽象构件角色(Component):定义参加组合的对象的共有方法和属性,可以定义一些默认的行为或属性;
- 叶子构件(Leaf):叶子对象,其下再也没有其他的分支。
- 树枝构件(Composite):树枝对象,它的作用是组合树枝节点和叶子节点;
组合模式有两种模式,透明模式和安全模式,这两个模式有什么区别呢?先看类图:
安全模式类图

透明模式类图

从类图上大家应该能看清楚了,这两种模式各有优缺点,透明模式是把用来组合使用的方法放到抽象类中,比如 add(),remove()以及 getChildren 等方法(顺便说一下,getChildren 一般返回的结果为 Iterable的实现类,很多,大家可以看 JDK 的帮助),不管叶子对象还是树枝对象都有相同的结构,通过判断是getChildren 的返回值确认是叶子节点还是树枝节点,如果处理不当,这个会在运行期出现问题的,不是很建议的方式;安全模式就不同了,它是把树枝节点和树叶节点彻底分开,树枝节点单独拥有用来组合的方法,这种方法比较安全,但是客户段无法依赖抽象(Component),违背了依赖倒置原则。
组合模式案例
我们接下来使用安全组合模式来完成一个示例,透明模式大家自行实验
我们有一个公司人事管理的的树状结构,如下图,我们用安全模式将这个梳树状结构实现出来

直接看代码:
/**
* 定义一个公司的人员的抽象类
*/
public abstract class Corp {
//公司每个人都有名称
protected String name = "";
//公司每个人都职位
protected String position = "";
//公司每个人都有薪水
protected int salary =0;
public Corp(String name, String position, int salary) {
this.name = name;
this.position = position;
this.salary = salary;
}
//获得员工信息
public abstract void getInfo();
}
/**
* 这些树枝节点也就是这些领导们既要有自己的信息,还要知道自己的下属情况
*/
public class Branch extends Corp{
//领导下边有那些下级领导和小兵
private List<Corp> subordinateList;
private Integer level;
//构造函数是必须的了
public Branch(String name, String position, int salary,Integer level) {
super(name, position, salary);
this.level=level;
this.subordinateList = new ArrayList<>();
}
//增加一个下属,可能是小头目,也可能是个小兵
public void addSubordinate(Corp corp) {
this.subordinateList.add(corp);
}
@Override
public void getInfo() {
String info = "";
info = "姓名:" + this.name;
info = info + "\t职位:"+ this.position;
info = info + "\t薪水:" + this.salary;
System.out.println(info);
for (Corp corp : this.subordinateList) {
//控制显示格式
if(this.level != null){
for (int i = 0; i < this.level; i++) {
//打印空格控制格式
System.out.print(" ");
}
for (int i = 0; i <this.level; i++) {
if( i == 0){
System.out.print("+");
}
System.out.print("_");
}
}
//打印名称
corp.getInfo();
}
}
}
/**
* 普通员工很简单,就写一个构造函数就可以了
*/
public class Leaf extends Corp{
public Leaf(String name, String position, int salary) {
super(name, position, salary);
}
//获得员工信息
@Override
public void getInfo(){
String info = "";
info = "姓名:" + this.name;
info = info + "\t职位:"+ this.position;
info = info + "\t薪水:" + this.salary;
System.out.println(info);
}
}
/**
* 组装这个树形结构,并展示出来
*/
public class Client {
public static void main(String[] args) {
//首先是组装一个组织结构出来
Branch ceo = compositeCorpTree();
//首先把CEO的信息打印出来:
ceo.getInfo();
//然后是所有员工信息
//System.out.println(getTreeInfo(ceo));
}
//把整个树组装出来
public static Branch compositeCorpTree() {
//首先产生总经理CEO
Branch root = new Branch("王大麻子", "总经理", 100000,1);
//把三个部门经理产生出来
Branch developDep = new Branch("刘大瘸子", "研发部门经理", 10000,2);
Branch salesDep = new Branch("马二拐子", "销售部门经理", 20000,2);
Branch financeDep = new Branch("赵三驼子", "财务部经理", 30000,2);
//再把三个小组长产生出来
Branch firstDevGroup = new Branch("杨三乜斜", "开发一组组长", 5000,3);
Branch secondDevGroup = new Branch("吴大棒槌", "开发二组组长", 6000,3);
//把所有的小兵都产生出来
Leaf a = new Leaf("a", "开发人员", 2000);
Leaf b = new Leaf("b", "开发人员", 2000);
Leaf c = new Leaf("c", "开发人员", 2000);
Leaf d = new Leaf("d", "开发人员", 2000);
Leaf e = new Leaf("e", "开发人员", 2000);
Leaf f = new Leaf("f", "开发人员", 2000);
Leaf g = new Leaf("g", "开发人员", 2000);
Leaf h = new Leaf("h", "销售人员", 5000);
Leaf i = new Leaf("i", "销售人员", 4000);
Leaf j = new Leaf("j", "财务人员", 5000);
Leaf k = new Leaf("k", "CEO秘书", 8000);
Leaf zhengLaoLiu = new Leaf("郑老六", "研发部副经理", 20000);
//开始组装
//CEO下有三个部门经理和一个秘书
root.addSubordinate(k);
root.addSubordinate(developDep);
root.addSubordinate(salesDep);
root.addSubordinate(financeDep);
//研发部经理
developDep.addSubordinate(zhengLaoLiu);
developDep.addSubordinate(firstDevGroup);
developDep.addSubordinate(secondDevGroup);
//看看开发两个开发小组下有什么
firstDevGroup.addSubordinate(a);
firstDevGroup.addSubordinate(b);
firstDevGroup.addSubordinate(c);
secondDevGroup.addSubordinate(d);
secondDevGroup.addSubordinate(e);
secondDevGroup.addSubordinate(f);
//再看销售部下的人员情况
salesDep.addSubordinate(h);
salesDep.addSubordinate(i);
//最后一个财务
financeDep.addSubordinate(j);
return root;
}
}
运行结果:
姓名:王大麻子 职位:总经理 薪水:100000
+_姓名:k 职位:CEO秘书 薪水:8000
+_姓名:刘大瘸子 职位:研发部门经理 薪水:10000
+__姓名:郑老六 职位:研发部副经理 薪水:20000
+__姓名:杨三乜斜 职位:开发一组组长 薪水:5000
+___姓名:a 职位:开发人员 薪水:2000
+___姓名:b 职位:开发人员 薪水:2000
+___姓名:c 职位:开发人员 薪水:2000
+__姓名:吴大棒槌 职位:开发二组组长 薪水:6000
+___姓名:d 职位:开发人员 薪水:2000
+___姓名:e 职位:开发人员 薪水:2000
+___姓名:f 职位:开发人员 薪水:2000
+_姓名:马二拐子 职位:销售部门经理 薪水:20000
+__姓名:h 职位:销售人员 薪水:5000
+__姓名:i 职位:销售人员 薪水:4000
+_姓名:赵三驼子 职位:财务部经理 薪水:30000
+__姓名:j 职位:财务人员 薪水:5000
组合模式在源码中的应用
- Java 的集合类-HashMap 就使用了组合模式,他里面有一个putAll()方法
- ArrayList也有addAll()方法,他也用了组合模式

420

被折叠的 条评论
为什么被折叠?



