一 . 模式动机
- 假设你要去请假,先交给老师,但请假时间太久,老师无法处理,需要院长批准,你又去找院长,院长也无法处理,要校长批准,你又去找校长。这样就变得非常麻烦因为每一级都需要你去,所以我们请假通常就是交给老师,老师不能批准的假条由老师交给院长,再由院长交给校长。
- 因此我们就有了职责链模式,职责链模式可以将请求的处理者组织成一条链,并使请求沿着链传递,由链上的处理者对请求进行相应的处理,客户端无需关系处理的细节以及请求的传递,需要将请求发送到链上即可,将请求的发送者和处理者解耦。
二 . 定义
- 职责链模式(Chain of Responsibility Pattern):避免请求者和接收者耦合在一起,让多个对象能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。因为翻译问题,又称为责任链模式,是一种对象行为模式。
三 . 模式结构
(图片来源于网络)
- Handler:抽象处理类
- Concrete Handler:具体处理类
四 . 模式分析
- 职责链可以是直线,环或者一个树形结构,最常见的就是直线
- 在抽象处理类的定义中,必须引用自身,这个引用就可以使这些Handler形成一个链的结构。
- 职责链模式中,很多对象由每一个对象对其下家的引用面连接起来形成一条链
- 请求在这条链,直到遇到能够处理请求的对象。
五 . 模式实例
-
请假是一个责任链模式的典型代表,如果我们要请假,时间短的我们的直接领导人就可以处理比准,时间长的必须向上级汇报由更上级处理。这里是实现一些
-
UML图
-
抽象处理类Leader
public abstract class Leader {
String name;
Leader nextleader;
public void setNextleader(Leader nextleader) {
this.nextleader = nextleader;
}
public Leader(String name) {
this.name = name;
}
public void handlerRequest(LeaveRequest leaveRequest){
}
}
- 具体处理类Director,Manger,General Manger
public class Director extends Leader {
public Director(String name) {
super(name);
}
public void handlerRequest(LeaveRequest leaveRequest){
if (leaveRequest.getDay()<10){
System.out.println(leaveRequest.name+"请假"+leaveRequest.getDay()+"成功");
System.out.println(this.name+"批准");
}else if(this.nextleader!=null){
this.nextleader.handlerRequest(leaveRequest);
}
}
}
public class Manger extends Leader {
public Manger(String name) {
super(name);
}
public void handlerRequest(LeaveRequest leaveRequest){
if (leaveRequest.getDay()<20){
System.out.println(leaveRequest.name+"请假"+leaveRequest.getDay()+"天成功");
System.out.println(this.name+"批准");
}else if(this.nextleader!=null){
this.nextleader.handlerRequest(leaveRequest);
}
}
}
public class GeneralManger extends Leader {
public GeneralManger(String name) {
super(name);
}
public void handlerRequest(LeaveRequest leaveRequest){
if (leaveRequest.getDay()<30){
System.out.println(leaveRequest.name+"请假"+leaveRequest.getDay()+"成功");
System.out.println(this.name+"批准");
}else {
System.out.println("批准辞职");
}
}
}
- 被处理类
public class LeaveRequest {
String name;
int day;
String reason;
public LeaveRequest(String name, int day, String reason) {
this.name = name;
this.day = day;
this.reason = reason;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public LeaveRequest() {
}
}
- 测试类
public class Client {
public static void main(String[] args) {
Director director = new Director("主任");
Manger manger = new Manger("经理");
GeneralManger generalManger = new GeneralManger("总经理");
director.setNextleader(manger);
manger.setNextleader(generalManger);
LeaveRequest leaveRequest = new LeaveRequest("张三",11,"回老家比赛");
director.handlerRequest(leaveRequest);
}
}
- 测试结果
E:\Java\jdk1.8.0_171\bin\java.exe "-javaagent:E:\idea\IntelliJ IDEA 2019.1.3\lib\idea_rt.jar=50858:E:\idea\IntelliJ IDEA 2019.1.3\bin" -Dfile.encoding=UTF-8 -classpath "E:\Java\jdk1.8.0_171\jre\lib\charsets.jar;E:\Java\jdk1.8.0_171\jre\lib\deploy.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\access-bridge-64.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\cldrdata.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\dnsns.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\jaccess.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\jfxrt.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\localedata.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\nashorn.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunec.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunjce_provider.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunmscapi.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunpkcs11.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\zipfs.jar;E:\Java\jdk1.8.0_171\jre\lib\javaws.jar;E:\Java\jdk1.8.0_171\jre\lib\jce.jar;E:\Java\jdk1.8.0_171\jre\lib\jfr.jar;E:\Java\jdk1.8.0_171\jre\lib\jfxswt.jar;E:\Java\jdk1.8.0_171\jre\lib\jsse.jar;E:\Java\jdk1.8.0_171\jre\lib\management-agent.jar;E:\Java\jdk1.8.0_171\jre\lib\plugin.jar;E:\Java\jdk1.8.0_171\jre\lib\resources.jar;E:\Java\jdk1.8.0_171\jre\lib\rt.jar;E:\Design pattern\out\production\Design pattern" ChainOfResponsibility责任链模式.Client
张三请假11天成功
经理批准
Process finished with exit code 0
六 . 职责链模式优缺点
- 优点
- 降低耦合度
- 可简化对象的相互连接
- 增强给对象指派职责的灵活性
- 增加新的请求处理类很方便
- 缺点
- 不能保证请求一定被接收
- 性能收到影响
七 . 适用环境和应用
- 适用环境
- 由多个对象可以处理同一个请求。
- 应用
- Java中的异常处理机制
八 . 模式扩展
- 纯与不纯的职责链模式
- 一个纯的职责链模式要求一个具体处理者对象只能在两个行为中选择一个:一个是承担责任,另一个是把责任推给下一个对象。不允许出现某一个具体处理者对象在承担了一部分责任后又将责任向下穿的情况。
- 不纯的责任链模式里,一个请求可以最终不被任何接收端对象所处理。