Java 设计模式15——责任链模式

本文链接:https://rainmonth.github.io/posts/J180324.html

模式定义

责任链模式,行为模式的一种,一个请求有多个对象处理,这些对象可以看成一条链,具体由哪个对象处理,有判断条件来决定,如果当前对象不能处理,则交给下一个对象处理,知道有对象处理为止。OkHttpClient就是利用责任链模式进行拦截器的处理的。

模式特点

将请求和处理分离开来,进行解耦。

涉及到的角色

  • 待处理的任务
  • 抽象的任务处理者(Handler):定义一个处理任务的抽象类,如果需要可以定义一个方法用来设定和返回下一个具体任务处理者的饮用;
  • 具体的任务处理者(ExactHandler):接收到请求后,如果满足处理条件,直接处理请求;不满足,将请求交给下家处理。所以具体处理者是持有下一个具体处理者对象的引用的,因而当前具体处理者可以访问下一个处理者。

使用场景

  • 有多个对象处理请求,如下例中,项目经理、部门经理及总经理都能处理请假这一请求;
  • 不知道具体由谁处理请求,如下例中,小明只是提交了请假的请求,他不必关心到底是谁处理的,只要知道处理结果就可以了
  • 处理请求的对象间的处理链可以动态设置;

举个栗子

一般公司有一个很常见的场景,那就是请假。小明所在的A公司又如下规定;

  1. 员工请假3天以内,由项目经理审批;
  2. 员工请假3至5天,由部门经理审批;
  3. 员工请假5天以上,由总经理审批;

代码实现

抽象处理者

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
/**
* 抽象处理者
*/
public static abstract class Handler {
private Handler nextHandler;
// 当前领导能审批通过的最多天数
public int maxDay;
protected Handler(int maxDay) {
this.maxDay = maxDay;
}
//设置责任链中下一个处理请求的对象
public void setNextHandler(Handler handler) {
nextHandler = handler;
}
protected void handleRequest(int day) {
if (day <= maxDay) {
reply(day);
} else {
if (nextHandler != null) {
//审批权限不够,继续上报
nextHandler.handleRequest(day);
} else {
System.out.println("没有更高的领导审批了");
}
}
}
protected abstract void reply(int day);
}

具体处理者

项目经理
1
2
3
4
5
6
7
8
9
10
11
12
/**
* 项目经理
*/
class ProjectManager extends Handler {
public ProjectManager(int day) {
super(day);
}
@Override
protected void reply(int day) {
LogUtil.d(day + "天请假,项目经理直接审批通过");
}
}
部门经理
1
2
3
4
5
6
7
8
9
10
11
12
/**
* 部门经理
*/
class DepartmentManager extends Handler {
public DepartmentManager(int day) {
super(day);
}
@Override
protected void reply(int day) {
LogUtil.d(day + "天请假,部门经理审批通过");
}
}
总经理
1
2
3
4
5
6
7
8
9
10
11
12
/**
* 总经理
*/
class GeneralManager extends Handler {
public GeneralManager(int day) {
super(day);
}
@Override
protected void reply(int day) {
LogUtil.d(day + "天请假,总经理审批通过");
}
}
实际情境模拟
1
2
3
4
5
6
7
8
9
10
11
12
public class Client {
public static void main(String[] args) {
Handler projectManager = new ProjectManager(3);
Handler departmentManager = new DepartmentManager(5);
Handler generalManager = new GeneralManager(15);
//创建职责链
projectManager.setNextHandler(departmentManager);
departmentManager.setNextHandler(generalManager);
//发起一次请求
projectManager.handleRequest(10);
}
}

输出

1
10天请假,总经理审批通过

在Android中的应用

  • View的事件处理

    用户点击了屏幕,产生了一个touch请求,交给界面上的View处理,如果第一层需要处理,就处理;不需要处理,交友下一层处理,依次类推,这里处理touch的每一层的View就是上面的具体处理者,View就是抽象处理者,View的dispatchTouchEvent方法就相当于责任链的构建者,由它来安排touch请求的处理顺序。

  • 有序广播(Ordered Broadcast)

    Ordered Broadcast的接收者将按预先声明的优先级依次接收 Broadcast 。如:A的级别高于B , B高于C 。那么,Broadcast先传给A ,再传给B ,最后传给C 。优先级声明在元素的Android:priority属性中,数越大优先级别越高,取值范围为 -1000~1000 。