行为型模式,可以让我们更好地划分类、对象之间的职责,并研究系统在运行时实例对象之间的交互。这里,我们来介绍第一种行为型设计模式——Chain Of Responsibility Pattern 责任链模式
模式思想
一般情况下,公司都有请假审批制度。比如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;
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
|
public class HR extends Manager {
public HR(String name) { super.setName(name); }
public void setLeader(Manager manager) { super.setLeader(manager); }
@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); }
@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); } } } ...
public class CEO extends Manager {
public CEO(String name) { super.setName(name); }
public void setLeader(Manager manager) { super.setLeader(manager); }
@Override public void approve(LeaveRequest leaveRequest) { if( leaveRequest.getDayNumber()<=10 ) { System.out.println("[CEO-"+ getName() +"]: 同意 <"+leaveRequest.getName()+"> 请" +leaveRequest.getDayNumber()+"天假"); } else { 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
|
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); } }
|
测试结果如下,符合预期
这里我们实现的责任链模式通常也被称作为纯的责任链模式,即处理者对于一个请求,要么全部处理完毕以结束该请求,要么一点也不处理直接把请求的处理责任传递给下一级处理者。而在更多场景下,我们使用的是一个不纯的责任链模式,即某个处理者只负责处理请求中的某一部分,然后将该请求传递到下一级处理者继续处理请求中的其它部分。责任链模式的典型应用有Servlet Filter
参考文献
- Head First 设计模式 弗里曼著