Java设计模式之责任链模式
前言
其实java中的责任链模式在代码中经常会用到,可能是对这些设计模式没做深入的理解和归纳总结,所以看到代码时会恍然大悟说自己经常看到,例如我们常用到的switch -case模版,if-else模版等,这些都是简单的设计模式,为了更好的理解其中的原理,所以对责任链这种设计模式做一个简单解析!
场景构建
针对一种特定的场景进行设计,利用责任链模式完成场景的全部逻辑,场景如下:
某公司员工要出差,出差这笔费用需要向上级汇报并申请,但是针对出差费过多的情况,可能会出现这位员工的直属上级没有权限批准,可能这位直属领导会向他的上级进行汇报申请,这样依次类推直到某个领导能有权限批准这笔费用为止!
逻辑图如下
==员工== ->==领导A==->==领导B==->==领导C==>->......->==领导N==
代码构建
先构建员工出差的类:
/**
* 员工A要出差
*/
public class Person {
private int money;
/**
* 设置出差需要非费用
*/
public void setMoney(int money) {
this.money = money;
}
/**
* 获取需要申请的出差费用
*/
public int getMoney() {
return money;
}
/**
* 向上级回报
*/
public void getApply() {
System.out.print("老大我需要的出差费用是" + getMoney());
}
}
他的上级依次是只能审批500的出差费用,审批1000的,审批1500的,审批2000的。
/**
* 申请500已下的金额可以批,大于500会向上级回报
*/
public class Leader500 {
public void handler(Person person) {
person.getApply();
System.out.print(" 我是Leader500 你需要申请的" + person.getMoney() + "我批准了");
}
}
/**
* 申请1000已下的金额可以批,大于1000会向上级回报
*/
public class Leader1000 {
public void handler(Person person) {
person.getApply();
System.out.print(" 我是Leader1000 你需要申请的" + person.getMoney() + "我批准了");
}
}
/**
* 申请1500已下的金额可以批,大于1500会向上级回报
*/
public class Leader1500 {
public void handler(Person person) {
person.getApply();
System.out.print(" 我是Leader1500 你需要申请的" + person.getMoney() + "我批准了");
}
}
/**
* 申请2000已下的金额可以批,大于2000会向上级回报
*/
public class Leader2000 {
public void handler(Person person) {
person.getApply();
System.out.print(" 我是Leader2000 你需要申请的" + person.getMoney() + "我批准了");
}
}
员工做一次简单的申请会进行这样的操作:
public static void main(String[] args) {
//领导们
Leader500 leader500 = new Leader500();
Leader1000 leader1000 = new Leader1000();
Leader1500 leader1500 = new Leader1500();
Leader2000 leader2000 = new Leader2000();
//申请人
Person person = new Person();
person.setMoney(2000);
if (person.getMoney() <= 500) {
leader500.handler(person);
} else if (person.getMoney() <= 1000) {
leader1000.handler(person);
} else if (person.getMoney() <= 1500) {
leader1500.handler(person);
} else if (person.getMoney() <= 2000) {
leader2000.handler(person);
}
}
当申请金额为2000时得到的结果是:
老大我需要的出差费用是2000 我是Leader2000 你需要申请的2000我批准了
优化
看到这里是不是很简单?虽然是简单,但是并不符合我们写代码的规范,所以我们先优化一下代码,优化代码的出发点如下:
- 具体是谁申请出差费用我们不管,我们只管申请出差需要做那些事!
- 具体是谁审批我们不需要纠结,我们只管审批需要做哪些事
针对以上两点,我们可以把申请人抽象成类,把审批人做成接口
申请人的抽象类如下:
/**
* 将申请人的操作抽象化 不需要关心是谁来申请出差费用 只关心出差申要做的事
*/
public abstract class ApplyInfo {
int money;
public abstract void setMoney(int money);
public abstract int getMoney();
public void getApply() {
System.out.print("老大我需要的出差费用是" + getMoney());
}
}
审批人的接口如下:
/**
* 将领导需要做的事抽象成接口
*/
public interface LeaderInfo {
void handler(ApplyInfo person);
}
这样我们再对员工与审批人进行构建实体类
实体员工类:
/**
* 申请人
*/
public class Person extends ApplyInfo {
@Override
public void setMoney(int money) {
super.money = money;
}
@Override
public int getMoney() {
return super.money;
}
}
实体审批人类:
/**
* 申请500已下的金额可以批,大于500会向上级回报
*/
public class Leader500 implements LeaderInfo {
@Override
public void handler(ApplyInfo person) {
person.getApply();
System.out.print(" 我是Leader500 你需要申请的" + person.getMoney() + "我批准了");
}
}
因为审批人都是实现相同的接口所以这里就不写完所有审批人的代码了,模版都是一样的。
这时员工做一次简单的申请会进行这样的操作:
//领导们
Leader500 leader500 = new Leader500();
Leader1000 leader1000 = new Leader1000();
Leader1500 leader1500 = new Leader1500();
Leader2000 leader2000 = new Leader2000();
//申请人
Person person = new Person();
person.setMoney(2000);
if (person.getMoney() <= 500) {
leader500.handler(person);
} else if (person.getMoney() <= 1000) {
leader1000.handler(person);
} else if (person.getMoney() <= 1500) {
leader1500.handler(person);
} else if (person.getMoney() <= 2000) {
leader2000.handler(person);
}
到这里有人会说代码跟前面的是一样的,这点没错,执行代码是一样的,但是我们优化了整个结构!
问题抛出
看到这里大家心中应该有一个疑惑,我们上边两次执行代码其实都是我们已经直到了需要申请多少钱的情况下直接用if-else if这样的模版进行申请的,这里根本就没有构成一个责任链中的链条模式,所以我们的代码还需要进行更多变化,于是我们在上边优化代码的结构下进行链式的构建,构建方法很简单!
申请人的抽象类基本没什么变化:
/**
* 将申请人的操作抽象化 不需要关心是谁来申请出差费用 只关心出差申要做的事
*/
public abstract class ApplyInfo {
int money;
public abstract void setMoney(int money);
public abstract int getMoney();
public void getApply() {
System.out.print("老大我需要的出差费用是" + getMoney());
}
}
申请人这个时候不能作为接口,必须抽象成类:
/**
* 将领导需要做的事抽象成类
*/
public abstract class LeaderInfo {
//当前领导审核的金额
int auditMoney;
//当前领导的上级领导
LeaderInfo superiorLeader;
//设置当前领导能审批的额度
public abstract void setCurrentMoney(int money);
//当前领导收到申请后处理的事情
public abstract void handler(ApplyInfo applyInfo);
//设置当前领导的上一级领导
public abstract void setSuperiorLeader(LeaderInfo superiorLeader);
//执行审批流程
public void dealInfo(ApplyInfo applyInfo) {
if (applyInfo.money <= auditMoney) {
handler(applyInfo);
} else {
superiorLeader.dealInfo(applyInfo);
}
}
}
这里面多了几行代码,分别解释一下:
- 增加了审批人设置当前人可以审批的金额
- 设置当前审批人的直属上级领导
- 当前审批人收到申请后要做的事
- 执行审批流程
这样开始构建申请人的实体类:
/**
* 申请人
*/
public class Person extends ApplyInfo {
@Override
public void setMoney(int money) {
super.money = money;
}
@Override
public int getMoney() {
return super.money;
}
}
领导们:
/**
* 申请500已下的金额可以批,大于500会向上级回报
*/
public class Leader500 extends LeaderInfo {
@Override
public void setCurrentMoney(int money) {
super.auditMoney = money;
}
@Override
public void handler(ApplyInfo applyInfo) {
applyInfo.getApply();
System.out.print(" 我是Leader500 你需要申请的" + applyInfo.getMoney() + "我批准了");
}
@Override
public void setSuperiorLeader(LeaderInfo superiorLeader) {
super.superiorLeader = superiorLeader;
}
}
剩下的领导们结构一样,不贴代码了
执行代码:
public static void main(String[] args) {
//领导们
Leader500 leader500 = new Leader500();
Leader1000 leader1000 = new Leader1000();
Leader1500 leader1500 = new Leader1500();
Leader2000 leader2000 = new Leader2000();
leader500.setCurrentMoney(500);
leader1000.setCurrentMoney(1000);
leader1500.setCurrentMoney(1500);
leader2000.setCurrentMoney(2000);
leader500.setSuperiorLeader(leader1000);
leader1000.setSuperiorLeader(leader1500);
leader1500.setSuperiorLeader(leader2000);
//申请人
Person person = new Person();
person.setMoney(2000);
leader500.dealInfo(person);
}
执行代码中,显示构建了领导实例对象,然后每个领导能审批的金额是多少进行设置,再对领导人的上级领导进行关联,这样领导人就形成了一条链,我们再将申请人放入这条链,让他从链的开头进行滚动执行,直到有领导审批为止!
总结
责任链模式非常简单,就是使多个对象都有计划处理请求,从而避免请求的发送者和接受者之间的耦合关系。将
这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
Android中很多地方用到了这个设计模式,例如事件的传递,okhttp中的拦截器等等!有兴趣的朋友可以研究一下。
提醒
需要源码的朋友可以发送请求到邮箱
imkobedroid@gmail.com
文章与代码有待改进!希望可以交流