文章目录
- 一、责任链(Chain of Responsibility)模式
- 二、责任链模式的结构
- 三、源码
- 四、纯的与不纯的责任链模式
- 五、总结
一、责任链(Chain of Responsibility)模式
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
这种模式和LinkedList的链状数据结构相识,节点之间有着联系。
责任链可能是一条直线、一个环链或者一个树结构的一部分。
比如:
二、责任链模式的结构
下面使用了一个责任链模式的最简单的实现。
责任链模式涉及到的角色如下所示:
● 抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
● 具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
三、源码
import lombok.Builder;
import lombok.Data;
@Data
public class LeaveRequest {
/**天数*/
private int leaveDays;
/**姓名*/
private String name;
public LeaveRequest(int leaveDays,String name){
this.leaveDays = leaveDays;
this.name = name;
}
}
抽象处理者角色:
/**
* 抽象处理者角色类
*/
public abstract class AbstractLeaveHandler {
/**直接主管审批处理的请假天数*/
protected int MIN = 1;
/**部门经理处理的请假天数*/
protected int MIDDLE = 3;
/**总经理处理的请假天数*/
protected int MAX = 30;
/**领导名称*/
protected String handlerName;
/**下一个处理节点(即更高级别的领导)*/
protected AbstractLeaveHandler nextHandler;
/**设置下一节点*/
public void setNextHandler(AbstractLeaveHandler handler){
this.nextHandler = handler;
}
/**处理请假的请求,子类实现*/
public abstract void handlerRequest(LeaveRequest request);
}
具体处理者角色:
/**
* @description: 直接主管处理类
*/
public class LeaderLeaveHandler extends AbstractLeaveHandler{
public LeaderLeaveHandler(String name) {
this.handlerName = name;
}
@Override
public void handlerRequest(LeaveRequest request) {
if(request.getLeaveDays() <= this.MIN){
System.out.println("直接主管:" + handlerName + ",已经处理;流程结束。");
return;
}
if(null != this.nextHandler){
this.nextHandler.handlerRequest(request);
}else{
System.out.println("审批拒绝!");
}
}
}
/**
* @description: 部门经理处理类
*/
public class ManagerLeaveHandler extends AbstractLeaveHandler {
public ManagerLeaveHandler(String name) {
this.handlerName = name;
}
@Override
public void handlerRequest(LeaveRequest request) {
if(request.getLeaveDays() >this.MIN && request.getLeaveDays() <= this.MIDDLE){
System.out.println("部门经理:" + handlerName + ",已经处理;流程结束。");
return;
}
if(null != this.nextHandler){
this.nextHandler.handlerRequest(request);
}else{
System.out.println("审批拒绝!");
}
}
}
/**
* @description: 总经理处理类
*/
public class CEOLeaveHandler extends AbstractLeaveHandler {
public CEOLeaveHandler(String name) {
this.handlerName = name;
}
@Override
public void handlerRequest(LeaveRequest request) {
if(request.getLeaveDays() > this.MIDDLE && request.getLeaveDays() <= this.MAX){
System.out.println("总经理:" + handlerName + ",已经处理;流程结束。");
return;
}
if(null != this.nextHandler){
this.nextHandler.handlerRequest(request);
}else{
System.out.println("审批拒绝!");
}
}
}
测试类:
public class ResponsibilityTest {
public static void main(String[] args) {
LeaveRequest request = new LeaveRequest(20,"李三");
AbstractLeaveHandler leaderLeaveHandler = new LeaderLeaveHandler("县令");
ManagerLeaveHandler managerLeaveHandler = new ManagerLeaveHandler("知府");
CEOLeaveHandler ceoLeaveHandler = new CEOLeaveHandler("京兆尹");
leaderLeaveHandler.setNextHandler(managerLeaveHandler);
managerLeaveHandler.setNextHandler(ceoLeaveHandler);
leaderLeaveHandler.handlerRequest(request);
}
}
运行结果:
总经理:京兆尹,已经处理;流程结束。
四、纯的与不纯的责任链模式
一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,而是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又 把责任向下传的情况。
在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接收;在一个不纯的责任链模式里面,一个请求可以最终不被任何接收端对象所接收。
纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。
五、总结
责任链主要重在责任分离处理,让各个节点各司其职。
责任链上的各个节点都有机会处理事务,但是也可能不会受理请求。
责任链比较长,调试时可能会比较麻烦。
责任链一般用于处理流程节点之类的实际业务场景中。
Spring拦截器链、servlet过滤器链等都采用了责任链设计模式。
优点:
1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很方便。
缺点:
1、不能保证请求一定被接收。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
3、可能不容易观察运行时的特征,有碍于除错。
使用场景:
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。