一、简介
组合模式常用于含有多个集合,每个集合又可能含有子集和或者子元素的情况,如项目经理下可能有项目组长,项目组长下有普通程序员,而销售经理下可能只有业务人员(当然有的也有销售组长,举个例子而已)。
代码示例
要求:
1、公司结构有总经理–经理–组长–普通人员(仅用作简单例子,真正的结构更加复杂);
2、公司发布工作任务下去,如果当前人员有下属职员则分配到下级人员;
抽象职员类:
public abstract class Staff{
//含有的下属(子类实现添加职员的方法需要用到该集合所以声明为protected)
protected List<Staff> subordinates = new ArrayList<>();
//上司(根据业务需求决定添加)
private Staff superior;
public Staff getSuperior() {
return superior;
}
public void setSuperior(Staff superior) {
this.superior = superior;
}
//是否是叶子节点(有下属的不是叶子节点)
@Override
public final boolean isReaf() {
//三元运算符,?前的表达式返回true则整个表达式为冒号左边部分,否则为右边部分
return this.subordinates .size()<0?true:false;
}
//添加职员的方法(子类实现)
public abstract void addStaff(Staff staff);
//重写toString方法
@Override
public String toString() {
return this.getClass().getSimpleName();
}
//工作(有下级就叫下级做事,没有下级自己做事)
public final void doWork(){
if(subordinates.size()>0){
System.out.println("我是 "+this+",我的上司是 "+this.getSuperior()+" 有下属叫下属做事");
callSomeOneDoWork();
return;
}
System.out.println("我是 "+this+",我的上司是 "+this.getSuperior()+" 没有下属自己做事");
}
//叫下属工作
public final void callSomeOneDoWork(){
Iterator<Staff> it = subordinates.iterator();
while(it.hasNext()){
it.next().doWork();
}
}
}
做事的 doWork() 方法定义为 final ,子类不能重写该方法(其他 final 方法同理),这里就是一个简单的模板方法模式,通过模板方法定义一个通用方法来增强程序的复用率(当然这里的使用是不合理的,毕竟每个人都有自己的工作内容,可以把功能内容单独封装为一个抽象函数由子类实现,再把自己做的事放在函数第一行,就形成了一个合理的模板方法模式了),当然这里把工作交给下级处理的方式也体现了责任链模式的工作方式(并不完善的责任链模式,以后再做介绍)。
经理、组长、程序员实现类:
//项目经理
public class ProjectManager extends Staff{
//初始化(有一个下属组长和一个下属程序员)
public ProjectManager() {
//初始化下属
GroupLeader leader = new GroupLeader();
Programmer programmer = new Programmer();
//为下属设置上司
leader.setSuperior(this);
programmer.setSuperior(this);
//添加下属
this.subordinates.add(leader);
this.subordinates.add(programmer);
}
@Override
//添加一个职员
public void addStaff(Staff staff){
this.subordinates.add(staff);
}
}
//项目组长
public class GroupLeader extends Staff{
public GroupLeader() {
//下属
Programmer p1 = new Programmer();
Programmer p2 = new Programmer();
//为下属设置上司
p1.setSuperior(this);
p2.setSuperior(this);
//为上司添加下属
this.subordinates.add(p1);
this.subordinates.add(p2);
}
@Override
public void addStaff(Staff staff) {
this.subordinates.add(staff);
}
}
//普通程序员
public class Programmer extends Staff{
@Override
//普通程序员没有下属,因此抛出一个异常表示不要去调用他
public void addStaff(Staff staff) {
throw new Exception();
}
}
其实添加职员的方法同样可以在抽象类中实现,在叶子节点上重写即可(这里为了表现的更像一个抽象类就添加这个抽象方法。。。完全可以直接实现,一个抽象类可以没有抽象方法,所以大家不要向我学习,毕竟可以节省不少代码)
场景模拟:
public class AssembleTest {
public static void main(String[] args) {
Staff staff = new ProjectManager();
staff.doWork();
}
}
场景非常简单,只需要有一个经理,让他去做事就可以了(客户就喜欢这么简单粗暴)
结果打印:
我是 ProjectManager,我的上司是 null 有下属叫下属做事
我是 GroupLeader,我的上司是 ProjectManager 有下属叫下属做事
我是 Programmer,我的上司是 GroupLeader 没有下属自己做事
我是 Programmer,我的上司是 GroupLeader 没有下属自己做事
我是 Programmer,我的上司是 ProjectManager 没有下属自己做事
(最后一个程序员的上司是经理哦,搞不好他就是下一个组长)
小结:
组合模式以一种树形结构完成,可以让客户将集合或元素都视为同一种对象,但是这种模式违反了单一职责的原则,所以具体场景根据实际情况抉择(对我而言,设计原则是为了更好的编码,编码则是为了完成业务功能,所以此时我觉得该用就用吧,功能实现的完美最重要)