责任链模式描述的是一种一对多的行为关系。一个任务被委派给多个人去执行,责任链模式规定的是这些人按照一定的顺序构成一个链条,任务在链条上挨个访问,如果任务被某个人给执行掉,则任务结束。
定义
使多个对象都有机会处理请求,避免请求发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有对象处理它为止
场景
- 多个对象可以处理同一个请求,具体由谁处理,需要在运行时动态决定
- 需要动态指定一组对象处理请求
- 在请求者不知道谁能处理自己的情况下,向多个接收者发送处理请求
角色
抽象处理者角色
声明一个处理请求的方法,并保持一个对下一个节点的引用
具体处理者角色
处理请求的角色,如果不能处理,则将请求传递给下一个具体处理者角色
抽象请求
请求的抽象接口,可能包含一个具体处理者角色
具体请求
具体的请求,具体处理者需要处理的事件
实现
具备三个要素
- 抽象处理类接口
- 抽象请求处理方法
- 请求对象
下面是抽象处理类的定义,重点是抽象处理方法以及指向下一个处理者的引用
/**
* 处理者抽象类
*/
public abstract class IHandler {
public IHandler next;
/**
* 处理请求抽象方法
*
* @param duty 请求
* @return 是否处理
*/
abstract boolean handle(IDuty duty);
}
看一下具体的处理类的实现
/**
* 具体处理者1
*/
public class FirstHandler extends IHandler {
private String deal = "HD";
/**
* 实现处理的方法
* @param duty 请求
* @return 是否处理成功
*/
@Override public boolean handle(IDuty duty) {
boolean done = this.deal.equals(duty.deal());
// 如果当前处理者没有处理掉请求,当还有处理者时,将请求传递给下一个处理者
if (!done && next != null) {
return next.handle(duty);
}
return done;
}
}
/**
* 具体处理者2
*/
public class SecondHandler extends IHandler {
private String deal = "DR";
@Override public boolean handle(IDuty duty) {
boolean done = this.deal.equals(duty.deal());
// 如果当前处理者没有处理掉请求,当还有处理者时,将请求传递给下一个处理者
if (!done && next != null) {
return next.handle(duty);
}
return done;
}
}
然后是抽象请求和具体请求
/**
* 抽象请求
*/
public interface IDuty {
/**
* 请求的部分逻辑(测试)
*/
String deal();
}
/**
* 具体请求
*/
public class DutyRequest implements IDuty {
/**
* 返回DR,在本次测试中,标记只有第二个处理者可以处理
*/
@Override public String deal() {
return "DR";
}
}
具体使用时,先构造处理链路,然后提交请求给第一个处理者
public void action(){
DutyRequest dr = new DutyRequest();
// 构建处理者链路
FirstHandler fh = new FirstHandler();
SecondHandler sh = new SecondHandler();
fh.next = sh;
sh.next = null;
// 从第一个角色开始处理
fh.handle(dr);
}
以上代码就模拟了一次利用责任链模式来编码处理请求的过程。可以看到,在这种模式下,请求事件和处理者之间没有强耦合,当有新的请求出现时,只需要构建新的请求,并派送给处理链路即可。
其实在安卓源码中,事件的处理就是一种典型的责任链模式。有兴趣的同学可以查看安卓事件分发源码验证一下。
总结
所有的设计模式都有自己的优点,同时也有自己的缺点,只是大多数优点都会大于缺点。责任链模式也一样。优点是可以将请求者和处理者关系解耦,提高代码的灵活性。缺点也很明显,就是需要对处理者链路进行遍历,当链路很长时间,可能会造成性能上的影响,特别是在递归调用时,这点需要注意。