设计模式-责任链模式

责任链模式(Chain of Responsibility): 避免讲一个请求的发送者与接收者耦合在一起让多个对象都有机会处理请求, 将接收请求的对象连成一条链, 并且沿着这条链传递请求, 直到有一个对象能够处理它为止.

设计模式-概述

结构

责任链模式结构很简单, 仅仅包含了两种角色:

  1. 抽象处理者(Handler): 定义了一个处理请求的接口, 一般设计为抽象类, 内部包含了一个下一家的处理者, 由此形成了一条链状结构.
  2. 具体处理者(ConcreteHandler): 是抽象类的子类, 内部包含对请求处理的具体实现.

chain-1.png

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
@startuml chain-1
!include common.cuml

Class(Handler,"抽象处理者") << abstract >> {
- successor: Handler
+ handleRequest()
}

Class(ConcreteHandlerA,"具体处理者A") {
+ handleRequest()
}

Class(ConcreteHandlerB,"具体处理者B") {
+ handleRequest()
}

Class(Client,"客户端") {
}

Client .right.> Handler
Handler o--> Handler : successor
Handler <|-- ConcreteHandlerA
Handler <|-- ConcreteHandlerB

@enduml

代码实现

  1. 实现了三个处理器, 并且维护好链接关系
  2. 启动第一个处理器, 如果符合条件, 下面的处理器也会执行, 如果不符合条件, 直接中断链处理.
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class Main2 {
public static void main(String[] args) {
ConcreteHandlerA concreteHandlerA = new ConcreteHandlerA();
ConcreteHandlerB concreteHandlerB = new ConcreteHandlerB();
ConcreteHandlerC concreteHandlerC = new ConcreteHandlerC();
concreteHandlerA.setSuccessor(concreteHandlerB);
concreteHandlerB.setSuccessor(concreteHandlerC);
concreteHandlerC.setSuccessor(null);
// 启动
concreteHandlerA.handleRequest("ABC");
System.out.println("=========================");
// 启动2
concreteHandlerA.handleRequest("AC");
}
}

abstract class Handler {
protected Handler successor;

public void setSuccessor(Handler successor) {
this.successor = successor;
}

public abstract void handleRequest(String request);
}

class ConcreteHandlerA extends Handler {

@Override
public void handleRequest(String request) {
System.out.println("ConcreteHandlerA.handleRequest start");
if (request.contains("A")) {
System.out.println("request contains A");
if (this.successor != null) {
this.successor.handleRequest(request);
}
} else {
System.out.println("ConcreteHandlerA.handleRequest end");
}
}
}

class ConcreteHandlerB extends Handler {

@Override
public void handleRequest(String request) {
System.out.println("ConcreteHandlerB.handleRequest start");
if (request.contains("B")) {
System.out.println("request contains B");
if (this.successor != null) {
this.successor.handleRequest(request);
}
} else {
System.out.println("ConcreteHandlerB.handleRequest end");
}
}
}

class ConcreteHandlerC extends Handler {

@Override
public void handleRequest(String request) {
System.out.println("ConcreteHandlerC.handleRequest start");
if (request.contains("C")) {
System.out.println("request contains C");
if (this.successor != null) {
this.successor.handleRequest(request);
}
} else {
System.out.println("ConcreteHandlerC.handleRequest end");
}
}
}

结果为:

1
2
3
4
5
6
7
8
9
10
11
ConcreteHandlerA.handleRequest start
request contains A
ConcreteHandlerB.handleRequest start
request contains B
ConcreteHandlerC.handleRequest start
request contains C
=========================
ConcreteHandlerA.handleRequest start
request contains A
ConcreteHandlerB.handleRequest start
ConcreteHandlerB.handleRequest end

使用场景

  1. 有多个对象需要同时处理某一个请求
  2. 各个处理器之间存在链式关系
  3. 可以动态的维护这个链关系, 可以改变链中各个处理器的执行先后顺序.

具体应用

  1. 我们常见的web应用中, 经常会对同一个httpRequest做多种处理, 并且这些处理比较通用时, 比如用户鉴权, 日志跟踪时都会用到
  2. Spring MVC 的 diapatcherServletdoDispatch() 方法中, 获取与请求匹配的处理器时, 通过getHandler()方法获取HandlerExcutionChain对象, getHandler()方法中, 通过遍历HandlerMappings查询到与request匹配的Handler对象.