一、介绍,定义
使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
二、使用场景
多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定。
在请求处理者不明确的情况下向多个对象中的一个提交一个请求。
需要动态指定一组对象处理请求。
三、UML类图
客户端发出请求,调用抽象类Handler中的方法处理逻辑业务。对象ConcreteHandler1与ConcreteHandler2继承Handler,其中ConcreteHandler1中持有下一个节点ConcreteHandler2的引用;事件由1对象发出,如果其处理不了,则交由2对象处理! 这是简单的责任链模式结构图,下面使用代码的方式展现:
四、通用模板
抽象处理者
public abstract class Handler {
//下一代处理者
public Handler nextProcessor;
// 每一个实现类处理
public abstract void handleRequest(String msg);
}
具体处理者
public class Processor1 extends Handler {
@Override
public void handleRequest(String msg) {
if(msg.equals("Processor1")) {
System.out.println("第一个处理者处理");
} else {
nextProcessor.handleRequest(msg);
}
}
}
public class Processor2 extends Handler {
@Override
public void handleRequest(String msg) {
if(msg.equals("Processor2")) {
System.out.println("第二个处理者处理");
} else {
nextProcessor.handleRequest(msg);
}
}
}
客户类
public class Client{
public static void main(String[] args) {
Processor1 processor1 = new Processor1();
Processor2 processor2 = new Processor2();
processor1.nextProcessor = processor2;
processor2.nextProcessor = processor1;
processor1.handleRequest("Processor2");
}
}
这只是一个简化版通用模式代码,大多数情况下,要将请求的规则和请求同时进行封装(这里只判断了字符串)
五、简单实现
小民去国外学习花了近10万块,于是找公司报销,向组长申请报销费用,组长一看这么大一笔钱,他哪里有这个权限,他手里最多才可以批1000块,于是组长就拿着票据去找部门主管,主管一看要报这么多钱,自己权限内只能批1万以下的费用,这完全超出了自己的权限范围呀,于是又只得去找上一级也就是经理,经理一看,我也只能批5万以下的费用啊。于是二话不说拿着票据直接奔向了老板的办公室,让老板去处理这个请求。
小民从链的底端开始发出一个申请报账的请求,首先由组长处理该请求,组长比对后发现自己权限不够,于是将该请求转发给位于该链中下一个节点的主管,主管比对后发现自己权限也不够,又只能将该请求转发给经理,而经理同样权限不够,毕竟10万块的大数目只有老板能处理,于是最后经理又将请求转发给了老板,这样层层转达直到请求被处理。
从中大家可以看到一个显而易见的事,就是至始至终小民只与组长产生了关联,后面具体由谁处理报销的票据,小民并不关心,只关心自己的票据(请求)有没有被成功处理。责任链模式在这里很好的将请求的发起者和处理者解耦。接下来我们用代码来实现这一过程。
public abstract class Leader {
protected Leader nextHandler;//上一级领导(处理者),UML图中的successor
/**
* 处理报账请求
* @param money 报账额度
* 申明为final,子类无法重写
*/
public final void handleRequest(double money){
if(money<=limit()){
handle(money);
}else{
if(null!=nextHandler){//有上一级处理者
nextHandler.handleRequest(money);
}else{
Log.e(getClass().getSimpleName(),"没有领导能批复你的票据报销啦,自己去报销吧!");
}
}
}
/**
* 自身能批复的报账额度
* @return 额度
*/
public abstract double limit();
/**
* 处理报账行为
* @param money 报账额度
*/
public abstract void handle(double money);
}
在这个抽象的领导类中只做了两件事,一是定义了两个抽象接口方法来确定一个领导者应有的行为和属性,二是声明了一个处理报账请求的方法来确定当前领导是否有能力处理报账请求,如果没有这权限,则将该请求转发给上级领导处理。接下来是各个具体的领导类的实现。
具体领导者,继承自抽象领导者类
//组长
public class GroupLeader extends Leader {
@Override
public double limit() {
return 1000;
}
@Override
public void handle(double money) {
Log.e(getClass().getSimpleName(),"组长批复报销了你的"+money+"元");
}
}
//主管
public class Director extends Leader {
@Override
public double limit() {
return 10000;
}
@Override
public void handle(double money) {
Log.e(getClass().getSimpleName(),"主管批复报销了你的"+money+"元");
}
}
//经理
public class Manager extends Leader {
@Override
public double limit() {
return 50000;
}
@Override
public void handle(double money) {
Log.e(getClass().getSimpleName(),"经理批复报销了你的"+money+"元");
}
}
//BOSS
public class Boss extends Leader {
@Override
public double limit() {
return 999999;
}
@Override
public void handle(double money) {
Log.e(getClass().getSimpleName(),"老板批复报销了你的"+money+"元");
}
}
具体领导类创建后,从组长开始发起请求申请报账
public class XiaoMin {
public static void main(String[] args){
protected void init() {
GroupLeader groupLeader = new GroupLeader();
Director director = new Director();
Manager manager = new Manager();
Boss boss = new Boss();
//设置上一级领导(处理者)对象
groupLeader.nextHandler = director;
director.nextHandler = manager;
manager.nextHandler = boss;
//发起报账申请
groupLeader.handleRequest(100000);
}
}
}
可以看到最后是BOSS处理了小民的报账申请,而且也只有BOSS才有这个权限处理,但是这里小民在申请的时候却只和组长进行了交流,降低了耦合度,这也是责任链模式的优点。当然这里我们代码也可以直接越过组长找主管或者经理或者直接找BOSS报账也是可以的,这也是责任链模式的灵活之处,请求的发起可以从责任链的任何一个节点开始,同时也可以改变责任链内部传递的规则,如主管不在,我们完全可以跨过主管直接将请求转送给经理。
六、模式的优缺点:
优点
- 降低耦合度:客户端不需要知道请求由哪个处理者处理,而处理者也不需要知道处理者之间的传递关系,由系统灵活的组织和分配。
- 良好的扩展性:增加处理者的实现很简单,只需重写处理请求业务逻辑的方法。
缺点 - 请求会从链头发出,直到有处理者响应,在责任链比较长的时候会影响系统性能。
- 请求递归,调试排错比较麻烦。
七、总结
对于责任链中的一个处理者对象,其只有两个行为,一是处理请求,二是将请求转送给下一个节点,不允许某个处理者对象在处理了请求后又将请求转送给上一级节点的情况。对于一条责任链来说,一个请求最终只有两种情况,一是被某个处理对象所处理,另一个是所有对象均未对其处理,对于前一种情况我们称该责任链为纯的责任链,对于后一种情况我们称为不纯的责任链,在实际应用中,我们所见到的责任链模式大多为不纯的责任链。