1 责任链模式概念
1.1 介绍
客户端发出一个请求,链上的对象都有机会来处理这一请求,而客户端不需要知道谁是具体的处理对象。这样就实现了请求者和接受者之间的解耦,并且在客户端可以实现动态的组合职责链。使编程更有灵活性。
1.2 定义
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。其过程实际上是一个递归调用。
1.3 使用场景
- 如果有多个对象可以处理同一个请求,但是具体由哪个对象处理是由运行时刻动态决定的,这种对象就可以使用职责链模式,把处理请求的对象实现成职责对象,然后构造链,当请求在这个链中传递的时候,会根据运行状态判断。
- 在请求处理者不明确的情况下向多个对象中的一个提交请求。
- 需要动态指定处理一个请求的对象集合。
2 责任链模式UML类图通用
Handler:定义职责接口,通常在内部定义处理请求的方法,可以在这里实现后继链。
ConcreteHandler:实际的职责类,在这里个类里面,实现在它职责范围内的请求处理,如果不处理,就继续转发请求给后继者。
-
Client:客户端,组装职责链,向链上的具体对象提交请求。
图中最关键的点就是:那条从Handler出发又指向自己的线,它就是实现链式调用的关键。
3 通用模式代码
(1)Handler抽象类
Handler抽象类作为职责接口,是所有职责对象的父类。
public abstract class Handler {
protected Handler successor;// 下一节点的处理者
/**
* 请求处理
*/
public abstract void handlerRequest(String condition);
}
(2)具体的职责实现对象
public class ConcreteHandler1 extends Handler {
@Override
public void handlerRequest(String condition) {
if (condition.equals("ConcreteHandler1")) {
System.out.println("ConcreteHandler1 处理事件");
return;
} else {
successor.handlerRequest(condition);
System.out.println("ConcreteHandler1 post事件");
}
}
}
public class ConcreteHandler2 extends Handler {
@Override
public void handlerRequest(String condition) {
if (condition.equals("ConcreteHandler2")) {
System.out.println("ConcreteHandler2 处理事件");
return;
} else {
successor.handlerRequest(condition);
System.out.println("ConcreteHandler2 post事件");
}
}
}
(3)Client客户端
public class Client {
public static void main(String[] args){
// 客户端需要自己组装职责链
Handler handler1=new ConcreteHandler1();// 构造职责对象
Handler handler2=new ConcreteHandler2();// 构造职责对象
// 设置handler1的下一个节点
handler1.successor = handler2;
// 设置handler2的下一个节点
handler2.successor = handler1;
// 发起请求
handler1.handlerRequest("ConcreteHandler2");
}
}
(4)测试结果
因为发出的请求不在ConcreteHandler1的处理范围,它将事件下发了,而ConcreteHandler2具有最高的权限范围,一定能处理请求。
(5)职责链的调用过程
4 责任链模式简单实现
(1)抽象领导类
public abstract class Leader {
protected Leader nextHandler;// 上级领导处理者
/**
* 处理报账请求
* @param money 能批复的报账额度
*/
public final void handleRequest(int money){
System.out.println(getLeader());
if(money <=limit()){
handle(money);
}else{
System.out.println("报账额度不足,提交领导");
if(null != nextHandler){
nextHandler.handleRequest(money);
}
}
}
/**
* 自身能批复的额度权限
* @return 额度
*/
public abstract int limit();
/**
* 处理报账行为
* @param money 具体金额
*/
public abstract void handle(int money);
/**
* 获取处理者
* @return 处理者
*/
public abstract String getLeader();
}
(2)组长(额度1000)
public class GroupLeader extends Leader{
@Override
public int limit() {
return 1000;
}
@Override
public void handle(int money) {
System.out.println("组长批复报销"+ money +"元");
}
@Override
public String getLeader() {
return "当前是组长";
}
}
(3)主管(额度5000)
public class Director extends Leader{
@Override
public int limit() {
return 5000;
}
@Override
public void handle(int money) {
System.out.println("主管批复报销"+ money +"元");
}
@Override
public String getLeader() {
return "当前是主管";
}
}
(4)经理(额度10000)
public class Manager extends Leader{
@Override
public int limit() {
return 10000;
}
@Override
public void handle(int money) {
System.out.println("经理批复报销"+ money +"元");
}
@Override
public String getLeader() {
return "当前是经理";
}
}
(5)老板(额度…)
public class Boss extends Leader{
@Override
public int limit() {
return Integer.MAX_VALUE;
}
@Override
public void handle(int money) {
System.out.println("老板批复报销"+ money +"元");
}
@Override
public String getLeader() {
return "当前是老板";
}
}
(6)发起申请
public class Client {
public static void main(String[] args) {
// 构造各个领导对象
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(8000);
}
}
(7)结果
当前是组长
报账额度不足,提交领导
当前是主管
报账额度不足,提交领导
当前是经理
经理批复报销8000元
责任链模式非常灵活,请求的发起可以从责任链的任何一个节点开始,也可以改变内部的传递规则。比如主管不在,我们完全可以跨过主管直接从组长那里转到经理。
5 Android源码中的责任链模式
5.1 View事件的分发处理
ViewGroup事件投递的递归调用就类似于一条责任链,一旦其寻找到责任者,那么将由责任者持有并消费掉该次事件,具体体现在View的onTouchEvent方法中返回值的设置,如果返回false,那么意味着当前的View不会是该次的责任人,将不会对其持有;如果返回true,此时View会持有该事件并不再向外传递。
5.2 广播
6 总结
对于责任链中的一个处理者对象,有两个行为。一是处理请求,二是将请求传递到下一节点,不允许某个处理者对象在处理了请求后又将请求传送给上一个节点的情况。
对于一条责任链来说,一个请求最终只有两种情况。一是被某个处理对象所处理,另一个是所有对象均未对其处理,对于前一种情况我们称为纯的责任链模式,后一种为不纯的责任链。实际中大多为不纯的责任链。
(1)优点。职责链模式的最主要功能就是:动态组合,请求者和接受者解耦。
请求者和接受者松散耦合:请求者不需要知道接受者,也不需要知道如何处理。每个职责对象只负责自己的职责范围,其他的交给后继者。各个组件间完全解耦。
动态组合职责:职责链模式会把功能分散到单独的职责对象中,然后在使用时动态的组合形成链,从而可以灵活的分配职责对象,也可以灵活的添加改变对象职责。
(2)缺点
产生很多细粒度的对象:因为功能处理都分散到了单独的职责对象中,每个对象功能单一,要把整个流程处理完,需要很多的职责对象,会产生大量的细粒度职责对象。
不一定能处理:每个职责对象都只负责自己的部分,这样就可以出现某个请求,即使把整个链走完,都没有职责对象处理它。这就需要提供默认处理,并且注意构造链的有效性。