GoF设计模式(十三):Chain Of Responsibility Pattern 责任链模式

行为型模式,可以让我们更好地划分类、对象之间的职责,并研究系统在运行时实例对象之间的交互。这里,我们来介绍第一种行为型设计模式——Chain Of Responsibility Pattern 责任链模式

abstract.jpeg

模式思想

一般情况下,公司都有请假审批制度。比如3天以内的请假申请只需HR行政批准即可,超过3天但在7天内的请假申请只需部门经理批准即可,超过7天的请假申请则只能交由总经理定夺。而这其实就是责任链模式的体现和应用,员工的请假申请在 HR->部门经理->总经理 这条责任链上进行传递,直到链上的某个处理者可以处理该请求。此举实现了请求的发送者、接收者之间的解耦。在责任链模式下,一般有两个角色:

  • 抽象处理者角色:作为一个抽象角色,其定义了处理者的请求处理方法。即下文示例的Manager类
  • 具体处理者角色:其是对抽象处理者角色的实现,实现了请求处理方法。通常该角色有多个类。每个具体处理者内部一般会持有下一级具体处理者的实例,以将多个具体处理者构造成一条链。当处理者发现自己无法处理该请求时,即会将请求沿着责任链向下一级进行传递,以便合适的处理者对其进行处理。即下文示例的HR、DeptManager、CEO类

实现

下面我们通过Java来实现上面的例子来让大家更好的理解该模式。在此之前,我们先来定义一个LeaveRequest类,用来描述员工的请假请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 员工的请假申请
*/
@Data
@AllArgsConstructor
public class LeaveRequest {
/**
* 员工姓名
*/
private String name;

/**
* 请假天数
*/
private Integer dayNumber;
}

为了处理员工的请假申请,我们来应用责任链模式,首先定义一个抽象处理者角色——即Manager类,可以看到其内部有一个leader属性用于持有该管理者的上级领导

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 抽象处理者:公司管理层
*/
@Data
public abstract class Manager {
/**
* 管理层姓名
*/
private String name;

/**
* 上级领导
*/
private Manager leader;

/**
* 审批员工的请假申请
* @param leaveRequest
*/
public abstract void approve(LeaveRequest leaveRequest);
}

现在,就让我们来实现具体处理者角色,即HR、DeptManager、CEO类。如果员工的请假天数在处理者的权限范围之内,则直接处理;否则,即会将请假申请交给上级领导来处理

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
83
84
85
86
87
88
89
90
91
92
93
94
95
/**
* 具体处理者:HR
*/
public class HR extends Manager {

public HR(String name) {
super.setName(name);
}

public void setLeader(Manager manager) {
super.setLeader(manager);
}

/**
* HR只能审批3天以内的请假申请,否则需要交由上级领导处理
* @param leaveRequest
*/
@Override
public void approve(LeaveRequest leaveRequest) {
// 权限范围内,直接自行审批
if( leaveRequest.getDayNumber()<=3 ) {
System.out.println("[HR-"+ getName() +"]: 同意 <"+leaveRequest.getName()+"> 请" +leaveRequest.getDayNumber()+"天假");
return;
}

// 如果有上级领导,交给上级领导审批
Manager leader = getLeader();
if( leader!=null ) {
System.out.println("[HR-"+ getName() +"]: 没权限批准,交给 "+leader.getName()+" 审批");
leader.approve(leaveRequest);
}
}
}
...
/**
* 具体处理者:部门经理
*/
public class DeptManager extends Manager {

public DeptManager(String name) {
super.setName(name);
}

public void setLeader(Manager manager) {
super.setLeader(manager);
}

/**
* 部门经理只能审批7天以内的请假申请,否则需要交由上级领导处理
* @param leaveRequest
*/
@Override
public void approve(LeaveRequest leaveRequest) {
// 权限范围内,直接自行审批
if( leaveRequest.getDayNumber()<=7 ) {
System.out.println("[DeptManager-"+ getName() +"]: 同意 <"+leaveRequest.getName()+"> 请" +leaveRequest.getDayNumber()+"天假");
return;
}

// 如果有上级领导,交给上级领导审批
Manager leader = getLeader();
if( leader!=null ) {
System.out.println("[DeptManager-"+ getName() +"]: 没权限批准,交给 "+leader.getName()+" 审批");
leader.approve(leaveRequest);
}
}
}
...
/**
* 具体处理者:CEO
*/
public class CEO extends Manager {

public CEO(String name) {
super.setName(name);
}

public void setLeader(Manager manager) {
super.setLeader(manager);
}

/**
* CEO批准10天以内的请假申请,否则拒绝该请假申请
* @param leaveRequest
*/
@Override
public void approve(LeaveRequest leaveRequest) {
// 只批准10天以内的请假申请
if( leaveRequest.getDayNumber()<=10 ) {
System.out.println("[CEO-"+ getName() +"]: 同意 <"+leaveRequest.getName()+"> 请" +leaveRequest.getDayNumber()+"天假");
} else { // 超过10天的请假申请不批准
System.out.println("[CEO-"+ getName() +"]: 不同意 <"+leaveRequest.getName()+"> 请" +leaveRequest.getDayNumber()+"天假");
}
}
}

现在,我们来看看client如何使用。这里为了方便起见,我们在client侧进行责任链的组装

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
/**
* Chain Of Responsibility Pattern 责任链模式
*/
public class ChainOfResponsibilityPatternDemo {
public static void main(String[] args) {

Manager hr = new HR("Tony");
Manager deptManager = new DeptManager("Amy");
Manager ceo = new CEO("David");
// 组装责任链
hr.setLeader(deptManager);
deptManager.setLeader(ceo);

System.out.println("----------- Test 1: 请1天假 -----------");
LeaveRequest leaveRequest1 = new LeaveRequest("小王", 1);
hr.approve(leaveRequest1);

System.out.println("\n----------- Test 2: 请5天假 -----------");
LeaveRequest leaveRequest2 = new LeaveRequest("小明", 5);
hr.approve(leaveRequest2);

System.out.println("\n----------- Test 3: 请8天假 -----------");
LeaveRequest leaveRequest3 = new LeaveRequest("小红", 8);
hr.approve(leaveRequest3);

System.out.println("\n----------- Test 4: 请55天假 -----------");
LeaveRequest leaveRequest4 = new LeaveRequest("小张", 55);
hr.approve(leaveRequest4);
}
}

测试结果如下,符合预期

figure 1.jpeg

这里我们实现的责任链模式通常也被称作为纯的责任链模式,即处理者对于一个请求,要么全部处理完毕以结束该请求,要么一点也不处理直接把请求的处理责任传递给下一级处理者。而在更多场景下,我们使用的是一个不纯的责任链模式,即某个处理者只负责处理请求中的某一部分,然后将该请求传递到下一级处理者继续处理请求中的其它部分。责任链模式的典型应用有Servlet Filter

参考文献

  1. Head First 设计模式 弗里曼著
0%