0%

责任链模式有几种写法

前言

本文结合设计模式中责任链模式的实现方式,看看 Android 源码和 OKHttp 等开源库中责任链模式的实现方式。

责任链模式

定义

责任链模式定义如下:Avoid coupling the sender of a request to its receiver by giving morethan one object a chance to handle the request.Chain the receivingobjects and pass the request along the chain until an object handles it.(使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。)

哪些场景需要责任链模式

实现

抽象处理者
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
74
75
76
77
78
79
80
81
82
public abstract class ResponseHandler {

private ResponseHandler nextHandler;

public abstract Level getLevel();

public abstract Response process(Request request);

public void setNextHandler(ResponseHandler next) {
nextHandler = next;
}

public final Response handleRequest(Request request) {
Response response = null;
if (this.getLevel().equals(request.getRequestLevel())) {
response = process(request);
} else {
if (nextHandler != null) {
response = nextHandler.handleRequest(request);
}
}
return response;
}

static class Level {
public int weight;

public Level(int weight) {
this.weight = weight;
}

@Override
public String toString() {
return "{" +
"weight=" + weight +
'}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Level level = (Level) o;
return weight == level.weight;
}

@Override
public int hashCode() {
return Objects.hash(weight);
}
}

static class Request {
public String input;
public Level level;

public Request(String input, Level level) {
this.input = input;
this.level = level;
}


public Level getRequestLevel() {
return this.level;
}
}

static class Response {
public String content;

public Response(String content) {
this.content = content;
}

@Override
public String toString() {
return "Response{" +
"content='" + content + '\'' +
'}';
}
}
}

抽象的处理者实现三个职责:

  1. 一是定义一个请求的处理方法handleMessage,唯一对外开放的方法;
  2. 二是定义一个链的编排方法setNext,设置下一个处理者;
  3. 三是定义了具体的请求者必须实现的两个方法:定义自己能够处理的级别 getLevel 和具体的处理任务process
具体的处理者
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
public class HandlerA extends ResponseHandler {
@Override
public Level getLevel() {
return new Level(0);
}

@Override
public Response process(Request request) {
System.out.printf("from %s process request %s \n", this.getClass().getSimpleName(), request.input);

String content = request.input + " level " + request.level;
request.level.weight++;
return new Response(content);
}
}

public class HandlerB extends ResponseHandler {
@Override
public Level getLevel() {
return new Level(1);
}

@Override
public Response process(Request request) {
System.out.printf("from %s process request %s \n", this.getClass().getSimpleName(), request.input);

String content = request.input + " level " + request.level;
request.level.weight++;
return new Response(content);
}
}

public class HandlerC extends ResponseHandler {
@Override
public Level getLevel() {
return new Level(2);
}

@Override
public Response process(Request request) {
System.out.printf("from %s process request %s \n", this.getClass().getSimpleName(), request.input);

String content = request.input + " level " + request.level;
request.level.weight++;
return new Response(content);
}
}

这里定义了三个具体的处理者。

调用者实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Client {
public static void main(String[] args) {
HandlerA handlerA = new HandlerA();
HandlerB handlerB = new HandlerB();
HandlerC handlerC = new HandlerC();

handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);

ResponseHandler.Level level = new ResponseHandler.Level(2);
ResponseHandler.Request request = new ResponseHandler.Request(" from client", level);

ResponseHandler.Response response = handlerA.handleRequest(request);

System.out.println(response);
}
}

output

1
2
from HandlerC process request  from client 
Response{content=' from client level {weight=2}'}

参考文档

加个鸡腿呗.