文章内容
一、什么是责任链模式
责任链模式,为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一个对象记住下一个对象的引用,而成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
责任链模式,也叫职责链模式,属于行为型设计模式。
二、责任链模式类图
三、责任链模式角色
- 抽象处理者角色(Handler):定义一个处理请求的接口,包含抽象处理方法和一个后续连接。
- 具体处理者角色(ConcreteHandler):实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理则处理,否则该请求转给它的后继者。
四、责任链模式优缺点
1、优点
- 降低了请求者和接受者对象之间的耦合度。
- 增强了系统的可扩展性,新增处理类时,满足开闭原则。
- 增强了给对象指派职责的灵活性:当流程工作发生变化时,可以根据需要动态调整责任链的顺序,也可新增或删除责任链。
- 责任链简化了对象之间的连接:一个责任链只需保持一个其后继者的引用,无需保持其它处理者的引用。
- 责任链分工明确:每个责任链只需要处理自己该处理的工作,不能处理的传递给下一个对象完成,满足单一职责原则
2、缺点
- 不能保证每个请求都能被处理。
- 对比较长的责任链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 责任链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能由于责任链的错误设置而导致系统出错。
五、责任链模式demo示例
1、Demo需求
以请假审批流程为例,公司员工请假审批流程是:员工请假天数小于3天,小组长审批;请假天数小于10天,部门经理审批;请假天数小于20天,副总经理审批;请假天数小于30天,总经理审批;请假天数超过30天,不予审批。
2、数据类定义
/**
* 请假类
*/ public class LeaveRequest {
//请假人
private String name;
//请假理由
private String reason;
//请假天数
private int day;
public LeaveRequest(String name, String reason, int day) {
this.name = name;
this.reason = reason;
this.day = day;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
}
3、抽象类定义
/**
* 抽象处理者角色:请假流程抽象类
*/ public abstract class Leader {
//审批人
protected String name;
//下一个审批者
protected Leader nextLeader;
public Leader(String name) {
this.name = name;
}
public void setNextLeader(Leader nextLeader) {
this.nextLeader = nextLeader;
}
/**
* 请假审批
* @param request
*/ public abstract void approve(LeaveRequest request);
}
4、具体化对象类
/**
* 具体处理者角色:小组长审批
*/ public class Headman extends Leader {
public Headman(String name) {
super(name);
}
public void approve(LeaveRequest request) {
//审批请假天数小于3天
if(request.getDay()<=3){
System.out.println("请假人:"+request.getName()+", 请假天数:"+request.getDay()+", 请假理由:"+request.getReason());
System.out.println("小组长:"+name+"审批通过");
}else {
if(nextLeader != null){
nextLeader.approve(request);
}
}
}
}
/**
* 具体处理者角色:部门经理审批
*/ public class DepartmentManager extends Leader {
public DepartmentManager(String name) {
super(name);
}
public void approve(LeaveRequest request) {
//审批请假天数大于3天小于10天
if(request.getDay()<=10){
System.out.println("请假人:"+request.getName()+", 请假天数:"+request.getDay()+", 请假理由:"+request.getReason());
System.out.println("部门经理:"+name+"审批通过");
}else {
if(nextLeader != null){
nextLeader.approve(request);
}
}
}
}
/**
* 具体处理者角色:副总经理审批
*/ public class ViceGeneralManager extends Leader {
public ViceGeneralManager(String name) {
super(name);
}
public void approve(LeaveRequest request) {
/**
* 审批天数大于10小于20天
*/ if(request.getDay()<=20){
System.out.println("请假人:"+request.getName()+", 请假天数:"+request.getDay()+", 请假理由:"+request.getReason());
System.out.println("副总经理:"+name+"审批通过");
}else {
if(nextLeader != null){
nextLeader.approve(request);
}
}
}
}
/**
* 具体处理者角色:总经理审批
*/ public class GeneralManager extends Leader {
public GeneralManager(String name) {
super(name);
}
public void approve(LeaveRequest request) {
//审批请假天数大于20天小于30天
if (request.getDay() <= 30) {
System.out.println("请假人:" + request.getName() + ", 请假天数:" + request.getDay() + ", 请假理由:" + request.getReason());
System.out.println("总经理:" + name + "审批通过");
} else {
if (nextLeader != null) {
nextLeader.approve(request);
} else {
System.out.println("请假人:" + request.getName() + ", 请假天数:" + request.getDay() + ", 请假理由:" + request.getReason());
System.out.println("请假天数太长无法审批,请提交请假天数小于30天。");
}
}
}
}
5、测试
/**
* 责任链模式客户端测试类
*/ public class Client {
public static void main(String[] args) {
Headman director = new Headman("李大帅");
DepartmentManager manager = new DepartmentManager("老王");
ViceGeneralManager viceGeneralManager = new ViceGeneralManager("赵副");
GeneralManager generalManager = new GeneralManager("胡总");
director.setNextLeader(manager);
manager.setNextLeader(viceGeneralManager);
viceGeneralManager.setNextLeader(generalManager);
LeaveRequest leaveRequest = new LeaveRequest("小王", "感冒了!", 1);
director.approve(leaveRequest);
System.out.println("============================================");
leaveRequest = new LeaveRequest("小李", "加班调休!", 6);
director.approve(leaveRequest);
System.out.println("============================================");
leaveRequest = new LeaveRequest("小胡", "回家探亲!", 12);
director.approve(leaveRequest);
System.out.println("============================================");
leaveRequest = new LeaveRequest("小吴", "回家探亲!", 30);
director.approve(leaveRequest);
System.out.println("============================================");
leaveRequest = new LeaveRequest("小张", "生病休养!", 36);
director.approve(leaveRequest);
}
}
请假人:小王, 请假天数:1, 请假理由:感冒了!
小组长:李大帅审批通过
============================================
请假人:小李, 请假天数:6, 请假理由:加班调休!
部门经理:老王审批通过
============================================
请假人:小胡, 请假天数:12, 请假理由:回家探亲!
副总经理:赵副审批通过
============================================
请假人:小吴, 请假天数:30, 请假理由:回家探亲!
总经理:胡总审批通过
============================================
请假人:小张, 请假天数:36, 请假理由:生病休养!
请假天数太长无法审批,请提交请假天数小于30天。