初探设计模式之【责任链设计模式】
一、场景
如果有这样一种场景:小明在出差期间因工作垫付了2400元,现在要向公司申请报销,审批报销的对象有直接领导(Maanger)、财务(accountant)、财务经理(accountantLeader)和老板(BOSS), 不同的级别有着不同的审批额度,他们的额度分别为:500元、1000元、3000元、5000元。
处理上面这样的审批业务,如何用代码实现呢?
二、传统实现
不使用设计模式,可能是类似于这样的流程:
public static void handle(int money) {
if (money <= 500) {
System.out.println("领导处理");
} else if (money <= 1000) {
System.out.println("财务处理");
} else if (money <= 3000) {
System.out.println("财务经理处理");
} else if (money <= 5000) {
System.out.println("老板处理");
} else {
System.out.println("超出额度,打回");
}
}
在实际处理上,由于这里涉及了不同的角色,你还需要创建所有的角色,如果逻辑复杂,比如区分不同的报销类型,在这些 if else 代码块中,需要加入大量的判断,一旦公司的报销制度发生变化,这里的代码都会发生大量的改动。
而在这里,其实每个角色处理的事情都不会跟其他人发生交集,每个人处理的都是独立的事情,我们至少可以将每个人处理的业务封装起来,当前一级处理不了时,就可以让下一级的人来处理。这里可以尝试用责任链设计模式来改造。
三、应用设计模式
首先我们可以创建一个审批者抽象类 Approver
, 他的核心逻辑是 执行审批逻辑,如果审批不了将事情丢给下一个人。所以他的实现如下:
public abstract class Approver {
protected String name;
protected Approver nextApprover;
public Approver(String name) {
this.name = name;
}
public Approver setNextApprover(Approver approver) {
this.nextApprover = approver;
return approver;
}
public abstract boolean handle(int value);
}
setNextApprover 方法可以将审批者,根据审批流程,形成一个链式的结构。
下面分别是4个审批者:
public class Manager extends Approver {
public Manager(String name) {
super(name);
}
@Override
public boolean handle(int value) {
if (value <= 500) {
System.out.println(name + ": 审批通过!");
return true;
} else {
System.out.println(name + ": 无法审批,传递给下一级!");
if (nextApprover != null) {
return nextApprover.handle(value);
} else {
return false;
}
}
}
}
public class Accountant extends Approver {
public Accountant(String name) {
super(name);
}
@Override
public boolean handle(int value) {
if (value <= 1000) {
System.out.println(name + ": 审批通过!");
return true;
} else {
System.out.println(name + ": 无法审批,传递给下一级!");
return nextApprover.handle(value);
}
}
}
public class AccountantLeader extends Approver {
public AccountantLeader(String name) {
super(name);
}
@Override
public boolean handle(int value) {
if (value <= 3000) {
System.out.println(name + ": 审批通过!");
return true;
} else {
System.out.println(name + ": 无法审批,传递给下一级!");
return nextApprover.handle(value);
}
}
}
再看客户端如何调用:
public static void main(String[] args) {
Approver approver1 = new Manager("领导");
Approver approver2 = new Accountant("财务");
Approver approver3 = new AccountantLeader("财务经理");
Approver approver4 = new BOSS("老板");
approver1.setNextApprover(approver2)
.setNextApprover(approver3)
.setNextApprover(approver4);
approver1.handle(2400);
}
通过 setNextApprover
方法,注入了下一级的审批对象。然后我们向直接上级提交审批申请,就不用理会后面的流程了,审批者们自己会去传递这个事件。
看下客户端调用时的打印:
领导: 无法审批,传递给下一级!
财务: 无法审批,传递给下一级!
财务经理: 审批通过!
四、总结
责任链模式允许业务请求者将责任链视为一个整体并对其发起请求,而不必关系链条内部具体的业务逻辑与流程走向。
这是《秒懂设计模式》对责任链设计模式的解释,android 中的事件分发机制跟这个很类似,就是由 DecorView 将点击事件传递下去,看应该由谁来处理,但他这个更复杂,正常情况下先要将事件传递到最底层,如果底层没有用户处理,再一层一层抛给上层处理,而且,在向底层传递的过程中,上层的一些处理者,还可以拦截事件,不让下一级的处理者参与进来。在 Android 开发中,OkHttp 网络库中的拦截器也使用了责任链,但区别是,它没有将拦截器形成一条链,而是放在两个集合中,第一个集合中的拦截器先处理,第二个则后处理,而每个集合中的拦截器其实没有先后之分,因为他们处理得事情都毫不相关,,一个人处理后,再给另一个人处理,在传递请求的过程中,是使用了一个index来记录当前传递的进度。
由此可以看出,设计模式给出的模版代码,仅仅是个参考,我们最应该关心的是他的核心思想,其实现方式,可以根据场景的变化而变化。