责任链模式

定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

责任链模式的关键是在上,链是由多个处理者ConcreteHandler组成,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应结果。

责任链模式通用类图责任链模式通用类图

实现

抽象处理者角色,定义一个处理请求的接口,包含抽象处理方法和一个后继连接,融合了模板方法模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract class AbstractChainHandler<T> {

private AbstractChainHandler next;

protected abstract <T> T doHandler(Object... obj);

protected abstract <T> boolean isAccordWith(T t);

public <T> T handler(Object... obj) {
T result = doHandler(obj);
if (!isAccordWith(result) && next != null) {
return (T) next.handler(obj);
} else {
return result;
}
}

public void setNext(AbstractChainHandler next) {
this.next = next;
}
}

具体处理者角色,实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class ConcreteChainHandler1<T> extends AbstractChainHandler<T> {
protected <T> T doHandler(Object... obj) {
// 具体业务逻辑
return null;
}

@Override
protected <T1> boolean isAccordWith(T1 t1) {
// 根据具体业务逻辑判断返回true还是false
return false;
}
}

public class ConcreteChainHandler2<T> extends AbstractChainHandler<T> {
protected <T> T doHandler(Object... obj) {
// 具体业务逻辑
return null;
}

@Override
protected <T1> boolean isAccordWith(T1 t1) {
// 根据具体业务逻辑判断返回true还是false
return false;
}
}

客户类角色,创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

1
2
3
4
5
6
public static void main(String[] args) {
AbstractChainHandler h1 = new ConcreteChainHandler1();
AbstractChainHandler h2 = new ConcreteChainHandler2();
h1.setNext(h2);
h1.handler(new Object[]{});
}

责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与被处理;独到之处是将其节点处理者组合成了链式结构,并允许节点自身决定是否进行请求处理或转发,相当于让请求流动起来。

优点

只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。所以责任链将请求的发送者和请求的处理者解耦了。

  • 降低了对象之间的耦合度,对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息
  • 增强了系统的可扩展性,可以根据需要增加新的请求处理类
  • 增强了给对象指派职责的灵活性,当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任
  • 简化了对象之间的连接,每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
  • 责任分担,每个类只需要处理自己该处理的工作

缺点

  • 不能保证每个请求一定被处理,没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理
  • 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响
  • 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用

应用场景

过滤器链的实现,Spring中的拦截器链

  • 多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。

  • 可动态指定一组对象处理请求,或添加新的处理者

  • 需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求