责任链模式
参考资料:https://refactoringguru.cn/design-patterns/chain-of-responsibility
概念
责任链模式(chain-of-responsibility)是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。
参考系统:OA审批流程 在线订货系统(权限管理)
传统方法:当收到一个请求后,根据采购的金额来指定不同的审批人,传统方法可以用if-else来进行判断或者switch进行解决,如果金额等级发生了改变的话,需要改动代码里的if-else条件,耦合度高,不利于代码的扩展和维护
解决方案:为请求创建一个接收者对象的链,对请求者和接收者进行解耦
责任链会将特定行为转换为被称作处理者的独立对象。 在上述示例中, 每个检查步骤都可被抽取为仅有单个方法的类, 并执行检查操作。 请求及其数据则会被作为参数传递给该方法。
模式建议你将这些处理者连成一条链。 链上的每个处理者都有一个成员变量来保存对于下一处理者的引用。 除了处理请求外, 处理者还负责沿着链传递请求。 请求会在链上移动, 直至所有处理者都有机会对其进行处理。
最重要的是: 处理者可以决定不再沿着链传递请求, 这可高效地取消所有后续处理步骤。
传统:处理者依次排列, 组成一条链。
责任链模式:对象树的枝干可以组成一条链。
所有处理者类均实现同一接口是关键所在。 每个具体处理者仅关心下一个包含
execute
执行方法的处理者。 这样一来, 你就可以在运行时使用不同的处理者来创建链, 而无需将相关代码与处理者的具体类进行耦合。
责任链模式结构
-
处理者 (Handler) 声明了所有具体处理者的通用接口。 该接口通常仅包含单个方法用于请求处理, 但有时其还会包含一个设置链上下个处理者的方法。
-
基础处理者 (Base Handler) 是一个可选的类, 你可以将所有处理者共用的样本代码放置在其中。
通常情况下, 该类中定义了一个保存对于下个处理者引用的成员变量。 客户端可通过将处理者传递给上个处理者的构造函数或设定方法来创建链。 该类还可以实现默认的处理行为: 确定下个处理者存在后再将请求传递给它。
-
具体处理者 (Concrete Handlers) 包含处理请求的实际代码。 每个处理者接收到请求后, 都必须决定是否进行处理, 以及是否沿着链传递请求。
处理者通常是独立且不可变的, 需要通过构造函数一次性地获得所有必要地数据。
-
客户端 (Client) 可根据程序逻辑一次性或者动态地生成链。 值得注意的是, 请求可发送给链上的任意一个处理者, 而非必须是第一个处理者。
Java代码实现
请假流程控制:
请假1天一下只需要组长审批
请假1-3天需要部门经理审批
请假3-7天需要总经理审批
请求实体类
@Data
public class Request {
/**
* 姓名
*/
private String name;
/**
* 请假天数
*/
private Integer num;
/**
* 请假内容
*/
private String content;
public Request(String name, Integer num, String content) {
this.name = name;
this.num = num;
this.content = content;
}
}
处理者 (Handler)
@Data
public abstract class Handler {
/**
* 请假的天数
*/
protected final static Integer NUM_ONE = 1;
protected final static Integer NUM_THREE = 3;
protected final static Integer NUM_SEVEN = 7;
/**
* 请假的区间
*/
private Integer numStart;
private Integer numEnd;
/**
* 构造方法
*
* @param numStart
* @param numEnd
*/
public Handler(Integer numStart, Integer numEnd) {
this.numStart = numStart;
this.numEnd = numEnd;
}
/**
* 下一个处理人(上级领导)
*/
private Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
/**
* 各级领导处理的方法
*
* @param request
*/
protected abstract void handleRequest(Request request);
public final void submit(Request request) {
if (this.getNumStart() < request.getNum() && this.getNumEnd() >= request.getNum()) {
this.handleRequest(request);
System.out.println("流程处理完成!");
} else if (this.nextHandler != null && request.getNum() > this.getNumEnd()) {
this.nextHandler.submit(request);
}
}
}
具体处理者 (Concrete Handlers)
public class GroupHandler extends Handler{
/**
* 构造方法
*
*/
public GroupHandler( ) {
super(0, Handler.NUM_ONE);
}
@Override
protected void handleRequest(Request request) {
System.out.println(MessageFormat.format("{0}请假{1}天,请假理由为:{2}",request.getName(), request.getNum(), request.getContent()));
System.out.println("组长审批同意!");
}
}
public class DeptManagerHandler extends Handler {
public DeptManagerHandler() {
super(Handler.NUM_ONE, Handler.NUM_THREE);
}
@Override
protected void handleRequest(Request request) {
System.out.println(MessageFormat.format("{0}请假{1}天,请假理由为:{2}", request.getName(), request.getNum(), request.getContent()));
System.out.println("部门经理审批同意!");
}
}
public class GeneralHandler extends Handler {
/**
* 构造方法
*/
public GeneralHandler() {
super(Handler.NUM_THREE, Handler.NUM_SEVEN);
}
@Override
protected void handleRequest(Request request) {
System.out.println(MessageFormat.format("{0}请假{1}天,请假理由为:{2}", request.getName(), request.getNum(), request.getContent()));
System.out.println("总经理审批同意!");
}
}
客户端 (Client)
public class Client {
public static void main(String[] args) {
Request leaveRequest1 = new Request("张三",1,"家里有事");
Request leaveRequest2 = new Request("李四",3,"家里有事");
Request leaveRequest3 = new Request("王五",7,"家里有事");
/**
* 创建各级领导对象
*/
GroupHandler groupHandler = new GroupHandler();
DeptManagerHandler deptManagerHandler = new DeptManagerHandler();
GeneralHandler generalHandler = new GeneralHandler();
/**
* 设置责任链
*/
groupHandler.setNextHandler(deptManagerHandler);
deptManagerHandler.setNextHandler(generalHandler);
/**
* 设置责任链的起点
*/
groupHandler.submit(leaveRequest1);
groupHandler.submit(leaveRequest2);
groupHandler.submit(leaveRequest3);
}
}
结果输出: