责任链模式
2020-07-06 本文已影响0人
一个菜鸟JAVA
什么是责任链模式
我们首先不讲概念,毕竟一上来讲概念很枯燥,而且看不懂.例如生活中,我们去银行贷款需要银行的工作人员审批.但是不同职位的工作人员审批的金额时不同的.假如前台的职员他只能批准1000元钱以下的贷款,而经理可以提供10000元以下的贷款,而行长的话可以批准100000元以下的贷款.如果金额更多的话就不提供贷款了.这就是一个很典型的责任链模式.当前用户如果无法处理的话,就将请求传递给下一个用户处理,如果下一个用户还是无法处理继续向下传递.这样直到被最后的节点处理.
案例代码
我们将上面的代码使用最普通的方式处理如下:
/**
* 贷款请求类
* Created by zengchao on 2020/7/3.
*/
public class LoanRequest {
/**
* 贷款人
*/
private String userName;
/**
* 贷款金额
*/
private Integer money;
public LoanRequest(String userName, Integer money) {
this.userName = userName;
this.money = money;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
@Override
public String toString() {
return "["+userName+"]申请贷款:"+money;
}
}
/**
* 贷款请求响应结果
* Created by zengchao on 2020/7/3.
*/
public class LoanResponse {
/**
* 贷款是否成功
*/
private Boolean success;
/**
* 备注信息
*/
private String remark;
public LoanResponse(Boolean success, String remark) {
this.success = success;
this.remark = remark;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
@Override
public String toString() {
return "贷款结果:["+(success ? "成功" : "失败") +"],原因:"+remark;
}
}
/**
* 贷款请求处理器
* Created by zengchao on 2020/7/3.
*/
public abstract class RequestHandler {
/**
* 下一个处理器
*/
private RequestHandler nextHandler;
/**
* 处理贷款请求
* @param request 贷款请求
* @return
*/
public abstract LoanResponse handler(LoanRequest request);
public RequestHandler(RequestHandler nextHandler) {
this.nextHandler = nextHandler;
}
public RequestHandler getNextHandler() {
return nextHandler;
}
}
/**
* 职员,只能处理金额低于1000元的贷款
* Created by zengchao on 2020/7/3.
*/
public class Staff extends RequestHandler{
public Staff(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public LoanResponse handler(LoanRequest request) {
System.out.println("职员处理贷款请求...");
if (request.getMoney() <= 1000){
return new LoanResponse(true,"申请贷款成功!处理人:职员");
}else {
System.out.println("职员当前无法处理贷款,交由下一人处理");
return getNextHandler().handler(request);
}
}
}
/**
* 经理.能处理10000以下的贷款请求
* Created by zengchao on 2020/7/3.
*/
public class Manager extends RequestHandler{
public Manager(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public LoanResponse handler(LoanRequest request) {
System.out.println("经理处理贷款请求...");
if (request.getMoney() <= 10000){
return new LoanResponse(true,"申请贷款成功!处理人:经理");
}else {
System.out.println("经理当前无法处理贷款,交由下一人处理");
return getNextHandler().handler(request);
}
}
}
public class President extends RequestHandler{
public President(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public LoanResponse handler(LoanRequest request) {
System.out.println("行长处理贷款请求...");
if (request.getMoney() <= 100000){
return new LoanResponse(true,"申请贷款成功!处理人:行长");
}else {
return new LoanResponse(false,"你申请的贷款金额太多了,行长也无法处理");
}
}
}
-
LoanRequest
:贷款请求对象.使用该类来表示一个贷款请求 -
LoanResponse
:贷款结果对象.使用该类来表示贷款申请的处理结果 -
RequestHandler
:贷款请求处理器,该类为抽象类.其中提供了处理贷款请求的方法和下一个处理者对象. -
Staff
:代表案例中职员,继承RequestHandler
类,其中包含了下一个处理者的引用. -
Manager
:代表案例中经理,继承RequestHandler
类,其中包含了下一个处理者的引用. -
President
:代表案例中行长,继承RequestHandler
类,其中包含了下一个处理者的引用.
public class App {
public static void main(String[] args) {
//创建行长
President president = new President(null);
//创建经理
Manager manager = new Manager(president);
//创建职员
Staff staff = new Staff(manager);
//小明申请贷款
LoanRequest req1 = new LoanRequest("小明", 2000);
System.out.println(req1);
LoanResponse res1 = staff.handler(req1);
System.out.println(res1);
//小黑申请贷款
System.out.println();
LoanRequest req2 = new LoanRequest("小黑", 200);
System.out.println(req2);
LoanResponse res2 = staff.handler(req2);
System.out.println(res2);
//小花申请贷款
System.out.println();
LoanRequest req3 = new LoanRequest("小花", 30000);
System.out.println(req3);
LoanResponse res3 = staff.handler(req3);
System.out.println(res3);
}
}
上面代码的打印结果如下:
[小明]申请贷款:2000
职员处理贷款请求...
职员当前无法处理贷款,交由下一人处理
经理处理贷款请求...
贷款结果:[成功],原因:申请贷款成功!处理人:经理
[小黑]申请贷款:200
职员处理贷款请求...
贷款结果:[成功],原因:申请贷款成功!处理人:职员
[小花]申请贷款:30000
职员处理贷款请求...
职员当前无法处理贷款,交由下一人处理
经理处理贷款请求...
经理当前无法处理贷款,交由下一人处理
行长处理贷款请求...
贷款结果:[失败],原因:你申请的贷款金额太多了,行长也无法处理
整个代码调用过程如下图所示:

上图很形象的表示了整个过程.所有的处理者通过一个向下的引用串在一条链上,然后请求一级一级传递形成了一个链条.这就是责任链模式.
定义
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止.
一般在这种模式中会有下面两个对象:
-
Handler(抽象处理者)
:它定义了一个请求的处理方法,且该方法一般为抽象方法,该类一般都为抽象类.因为不同的处理者的处理逻辑是不同的.同时该类中还会定义一个Handler
属性用来代表下一个处理者.我们上面的例子中该类就是RequestHandler
. -
ConcreteHandler(具体处理者)
:它一般是Handler
的子类,它可以处理用户的请求.在处理请求前它会先看自己是不是能处理该请求,如果不能,它将调用下一个处理者处理.我们上面的例子中该类就是:Staff
,Manager
和President
.
客户端在使用时,只需要根据自己的需求来配置链条节点即可.
优点
- 可以让调用者无需知道到底是哪一个处理者处理了请求,仅需要知道请求会被处理就可以了.处理者和发送者都不需要关心对方具体实现.客户端只需要配置链条即可,降低了系统的耦合性.
- 处理节点只需要维护下一个处理节点即可,不需要维护链条上所有的处理者.
- 我们可以灵活的增加和删除链条上的节点,当我们需要增加一个处理者或者删除一个处理者,只需要重新配置链条即可.同时更加明确了每个节点处理者的职责.
缺点
- 如果链条太长对系统的性能可能有部分影响,同时不太利于我们平常的调试.
- 如果链条形成环,很可能导致处理过程进入死循环.
纯责任链模式和不纯责任链模式
在一个纯的责任链模式中,要求一个具体的处理者对象只能全部承担责任或者传递给下一个.不允许一个处理者处理了一部分又再交给下一个处理者.我们例子中所说的这种便是纯责任链模式.而在我们实际开发中,使用不纯责任链模式更多.在不纯责任链模式中,允许一个处理者处理一部分之后,接着传递给下一个处理者继续处理.最常见的就是servelt
中的过滤器filter
,它通过多个过滤器组合,实现各种不同的功能.每个处理器都可以对请求和响应做部分处理.