Zer0e's Blog

设计模式之责任链模式

字数统计: 1k阅读时长: 3 min
2020/09/05 Share

前言

本文来谈谈责任链模式。

正文

概念

责任链模式属于行为型模式。正如名字所说一样,对象是一个链式的结构,当请求到达对象时,如果第一个对象不能处理这个请求,则将请求传递给下一个对象,以此类推。
责任链可以是直线型,也可以是环形,又或者是树形。那这种设计模式简化了请求传递的复杂度,请求只要传递给责任链上,并且无需关心如何处理请求,所以责任链模式将请求者与接受者解耦了。
那我们常见的场景有:

  • js中的事件冒泡,事件会依次向上传递。
  • jvm中的类加载机制也是责任链模式,但会一直指派到最顶级的类加载。

实现

责任链模式中有两个角色:

  • 抽象处理者(Handler):抽象对象或者接口。定义一个处理请求的接口。
  • 具体处理者(ConcreteHandler):具体的请求处理者,接收请求后选择是否处理请求,如不处理,则传递给下一位。

我们先用简单的例子:
首先创建handler:

1
2
3
4
5
6
7
8
9
10
11
12
13
public abstract class Handler {
// 下一个处理者
protected Handler nextHandler;

public Handler getNextHandler() {
return nextHandler;
}

public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handlerRequest(String name);
}

随后我们创建具体的处理者:

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
public class ConcreteHandlerA extends Handler{
@Override
public void handlerRequest(String name) {
if (name.equals("A")){
System.out.println("handler A 处理请求");
return;
}

if (getNextHandler() != null){
System.out.println("handler A 无法处理请求,转交给下一个handler");
getNextHandler().handlerRequest(name);
return;
}

System.out.println("所有handler都无法处理请求");
}
}
public class ConcreteHandlerB extends Handler{
@Override
public void handlerRequest(String name) {
if (name.equals("B")){
System.out.println("handler B 处理请求");
return;
}

if (getNextHandler() != null){
System.out.println("handler B 无法处理请求,转交给下一个handler");
getNextHandler().handlerRequest(name);
return;
}

System.out.println("所有handler都无法处理请求");
}
}

这里我们重写handlerRequest方法,当这个具体处理者可以处理请求时,直接处理请求,不能处理时,我们传给责任链中下一个处理者,如果没有下一个处理者就退出。
最后是客户端,其中客户端中我们需要显式地构建责任链。我们编写客户端试试:

1
2
3
4
5
6
7
8
9
10
public class Client {
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();

handlerA.setNextHandler(handlerB);

handlerA.handlerRequest("C");
}
}

这里我们将handlerA 的下一个责任链对象设置为handlerB,这样所有的handler形成了一个链表,我们只需将所有请求发送给handlerA,就无需关心请求是如何进行处理是谁处理的。

常见需求场景

所以责任链模式适用于一级一级传递的需求当中。比如日志管理,那我们常见的日志级别就是一级一级的,有debug,info,warning,error等等的级别,当日志级别设为较低一级时,它以上的日志都会打印。
又比如权限的管理,比如操作的级别有很多级,对服务器越危险的操作就必须有更高权限的人来确认操作,那根据操作的级别,把请求传递给责任链,权限不足就交给上一级,直到这个操作进行确认。
这里感兴趣的同学可以动手写写简单的实现代码。

优缺点

那责任链模式能一定程序上降低请求的发送者与处理者之间的耦合,不用关心请求发送给哪个处理者。其次对于指派处理者较为灵活,可以改变链中的顺序和成员,动态增加和删除。
那缺点在于不能保证请求一定被接收,其次就是环的解决,如果处理不当,有可能导致循环调用。

CATALOG
  1. 1. 前言
  2. 2. 正文
    1. 2.1. 概念
    2. 2.2. 实现
    3. 2.3. 常见需求场景
    4. 2.4. 优缺点