责任链概述:
责任链模式是一种行为设计模式之一。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
责任链模式涉及到的角色如下所示:
- 抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
- 具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
举例:
/**
* @author liuml
* @explain 抽象责任链
* @time 2018/8/6 20:37
*/
public abstract class HandlerChain {
protected HandlerChain mHandlerChain; //下一节点的处理者.
//设置下一级责任链
public void setSuccessor(HandlerChain handlerChain){
this.mHandlerChain = handlerChain;
}
public abstract void requext(int request);
}
/**
* @author liuml
* @explain 具体责任链一
* @time 2018/8/7 11:23
*/
public class ConcretHandler1 extends HandlerChain {
@Override
public void requext(int request) {
if (request < 10) {
System.out.println("我是责任链第一级 我处理了请求" + request);
}else{
this.mHandlerChain.requext(request);
}
}
}
/**
* @author liuml
* @explain 具体责任链2
* @time 2018/8/7 11:23
*/
public class ConcretHandler2 extends HandlerChain {
@Override
public void requext(int request) {
if (request > 10) {
System.out.println("我是责任链第二级 我处理了请求" + request);
} else {
System.out.println("请求" + request + "没人能够处理");
}
}
}
测试
public class Main {
public static void main(String[] args) {
//创建处理器
ConcretHandler1 concretHandler1 = new ConcretHandler1();
ConcretHandler2 concretHandler2 = new ConcretHandler2();
//客户端创建处理的关联,形成链
concretHandler1.setSuccessor(concretHandler2);
//创建任务, 此处为一些数字 大小不同, 处理器处理结果也不同;
int[] requests = {1, 10, 23, 40};
for (int request : requests) {
concretHandler1.requext(request);
}
}
}
打印结果
我是责任链第一级 我处理了请求1
请求10没人能够处理
我是责任链第二级 我处理了请求23
我是责任链第二级 我处理了请求40
描述和例子出自 百度百科 和 https://blog.csdn.net/disiwei1012/article/details/53557436
在android开发中实际的运用
举一个实际的例子. 在android开发中, 如果用户有可能有不同角色, 并且每个角色限可以进入不同的模块 一般情况下怎么做?
比如 role 的值 为 1 2 3 代表3个段位, 倔强青铜, 璀璨白银, 荣耀黄金.
下面这个模块只能 白银以上段位才能进入 一般都这么做
if(role==2||role==3){
//可以进入
}else{
//不可以进入
}
//或者
if(role>=2){
//可以进入
}else{
//不可以进入
}
或者需要每个权限对应每个模块做出某种操作
if(role ==1 ){
}else if(role == 2){
}else {
}
也可能7个段位 我这里就先写三个
//华贵铂金, 璀璨钻石, 超凡大师 , 最强王者 (我的lol很久没玩了)
一个模块还好 假如 app 模块慢慢增多 权限越加越多, 怎么办, 如果在这个代码下修改那就违法了开闭原则, 代码也不好维护.
使用责任链模式,
改造下 上面的代码
/**
* @author liuml
* @explain 抽象责任链
* @time 2018/8/6 20:37
*/
public abstract class HandlerChain {
protected HandlerChain mHandlerChain; //下一节点的处理者.
//设置下一级责任链
public void setSuccessor(HandlerChain handlerChain){
this.mHandlerChain = handlerChain;
}
public abstract boolean requext(int request);
}
/**
* @author liuml
* @explain 不屈青铜
* @time 2018/8/7 11:23
*/
public class ConcretHandler1 extends HandlerChain {
int role = 1;
@Override
public boolean requext(int request) {
if (Constant.role >= request && Constant.role == role) {
System.out.println("不屈黄铜 处理了请求 " + request);
return true;
} else {
return this.mHandlerChain.requext(request);
}
}
}
/**
* @author liuml
* @explain 璀璨白银
* @time 2018/8/7 11:23
*/
public class ConcretHandler2 extends HandlerChain {
int role = 2;
@Override
public boolean requext(int request) {
if (Constant.role >= request && Constant.role == role) {
System.out.println("璀璨白银 处理了请求" + request);
return true;
} else {
return mHandlerChain.requext(request);
}
}
}
/**
* @author liuml
* @explain 荣耀黄金
* @time 2018/8/7 11:23
*/
public class ConcretHandler3 extends HandlerChain {
int role = 2;
@Override
public boolean requext(int request) {
if (Constant.role >= request && Constant.role == role) {
System.out.println("荣耀黄金 处理了请求 " + request);
return true;
} else {
System.out.println("当前权限 "+Constant.role+", 请求" + request + "没人能够处理");
return false;
}
}
}
//常量 当前的权限
public class Constant {
public static int role = 2;
}
/**
* @author liuml
* @explain
* @time 2018/8/7 16:53
*/
public class HandlerChainStaticFactory {
public static ConcretHandler1 createOne(){
return new ConcretHandler1();
}
public static ConcretHandler2 createTwo(){
return new ConcretHandler2();
}
public static ConcretHandler3 createThree(){
return new ConcretHandler3();
}
}
/**
* @author liuml
* @explain 静态内部类单例
* @time 2018/8/7 16:55
*/
public class HandlerChainUtil {
private static ConcretHandler1 mConcretHandler1 = null;
private final ConcretHandler2 mConcretHandler2;
private final ConcretHandler3 mConcretHandler3;
public HandlerChainUtil(){
//创建处理器
mConcretHandler1 = HandlerChainStaticFactory.createOne();
mConcretHandler2 = new ConcretHandler2();
mConcretHandler3 = new ConcretHandler3();
//客户端创建处理的关联,形成链
mConcretHandler1.setSuccessor(mConcretHandler2);
mConcretHandler2.setSuccessor(mConcretHandler3);
}
public static HandlerChainUtil getInstance(){
return HandlerChainUtilHolder.sHandlerChainUtil;
}
public static boolean request(int request){
return mConcretHandler1.requext(request);
}
public static class HandlerChainUtilHolder{
public static final HandlerChainUtil sHandlerChainUtil = new HandlerChainUtil();
}
}
public class Main {
public static void main(String[] args) {
System.out.println("测试是否有权限: "+HandlerChainUtil.getInstance().request(2)+"\n");
System.out.println("测试是否有权限: "+HandlerChainUtil.getInstance().request(1)+"\n");
System.out.println("测试是否有权限: "+HandlerChainUtil.getInstance().request(3)+"\n");
System.out.println("测试是否有权限: "+HandlerChainUtil.getInstance().request(4)+"\n");
}
}
最后打印:
璀璨白银 处理了请求2
测试是否有权限: true
璀璨白银 处理了请求1
测试是否有权限: true
当前权限 2, 请求3没人能够处理
测试是否有权限: false
当前权限 2, 请求4没人能够处理
测试是否有权限: false
责任链模式的适用场景
就像上面的例子那样,假如使用if…else…语句来组织一个责任链时感到力不从心,代码看上去很糟糕时,就可以使用责任链模式来进行重构。
另外:
==有序广播也可以实现责任链模式==
开源框架 okhttp 责任链模式的使用