现需要实现一个休假审批功能,大致流程就是员工发起请假,然后需要经过各级领导审批后方能通过,使用传统的 if else 实现大致应该需要下面这么写:
if(一级审批通过) {
if(二级审批通过) {
if(三级审批通过) {
// ....
}
}
}
从功能实现角度来说毫无问题,但如想要做到动态就很麻烦了,比如中间多了一层审批,这种写法处理起来就有点麻烦了。
结合 Java 责任链模式就可以动态解决这个问题!
责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。
/**
*
* @author GodSea
*/
public abstract class ChainHandler {
/**
* 下一个处理链
*/
protected ChainHandler nextHandler;
public void setNext(ChainHandler nextHandler) {
this.nextHandler = nextHandler;
}
/**
* 处理方法
*/
public abstract void handler();
}
1.一级审批
/**
* 一级审批
* @author GodSea
*/
public class FirstChainHandler extends ChainHandler {
@Override
public void handler() {
if(approval()) {
System.err.println("一级审批通过");
if(this.nextHandler != null) {
System.err.println("进入二级审批");
this.nextHandler.handler();
} else {
System.err.println("审批结束");
}
} else {
System.err.println("一级审批拒绝");
}
}
private boolean approval() {
// 执行一级审批处理或审批结果查询
// ................
return (int) (Math.random() * 5) < 4;
}
}
2.二级审批
/**
* 二级审批
* @author GodSea
*/
public class SecondChainHandler extends ChainHandler {
@Override
public void handler() {
if(approval()) {
System.err.println("二级审批通过");
if(this.nextHandler != null) {
System.err.println("进入三级审批");
this.nextHandler.handler();
} else {
System.err.println("审批结束");
}
} else {
System.err.println("二级审批拒绝");
}
}
private boolean approval() {
// 执行二级审批处理或审批结果查询
// ................
return (int) (Math.random() * 5) < 4;
}
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ChainEntity {
private Integer id;
private String name;
private String conf;
private Integer preId;
private Integer nextId;
}
public enum ChainEnum {
/**一级审批*/
FIRST_APPROVAL(new ChainEntity(1, "一级审批", "com.example.mqtest.links.impl.FirstChainHandler", null, 2)),
/**二级审批*/
SECOND_APPROVAL(new ChainEntity(2, "二级审批", "com.example.mqtest.links.impl.SecondChainHandler", 1, null)),
;
ChainEntity gatewayEntity;
public ChainEntity getGatewayEntity() {
return gatewayEntity;
}
ChainEnum(ChainEntity gatewayEntity) {
this.gatewayEntity = gatewayEntity;
}
/**
* 根据 ID 获取责任链处理项
* @param id
* @return
*/
public static ChainEntity getChainEntityWithId(int id) {
for (ChainEnum value : ChainEnum.values()) {
if(value.getGatewayEntity().getId() == id) {
return value.getGatewayEntity();
}
}
return null;
}
/**
* 获取责任链第一个处理项
* @return
*/
public static ChainEntity getFirstGatewayEntity() {
for (ChainEnum value : ChainEnum.values()) {
if(value.getGatewayEntity().getPreId() == null) {
return value.getGatewayEntity();
}
}
return null;
}
}
public class Test {
public static void main(String[] args) {
// 获取责任链第一个处理项
ChainEntity firstGatewayEntity = ChainEnum.getFirstGatewayEntity();
if(firstGatewayEntity == null) {
return;
}
// 加载处理项
ChainHandler firstChainHandler = loadChainHandler(firstGatewayEntity);
if(firstChainHandler == null) {
return;
}
ChainEntity chainEntityTemp = firstGatewayEntity;
ChainHandler chainHandlerTemp = firstChainHandler;
// 迭代遍历所有handler,以及将它们链接起来
while (chainEntityTemp.getNextId() != null) {
ChainEntity chainEntityWithId = ChainEnum.getChainEntityWithId(chainEntityTemp.getNextId());
ChainHandler chainHandler = loadChainHandler(chainEntityWithId);
if(chainHandler == null) {
continue;
}
chainHandlerTemp.setNext(chainHandler);
chainEntityTemp = chainEntityWithId;
chainHandlerTemp = chainHandler;
}
firstChainHandler.handler();
}
private static ChainHandler loadChainHandler(ChainEntity firstGatewayEntity) {
try {
return (ChainHandler) Class.forName(firstGatewayEntity.getConf()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
1.一级审批直接拒绝
2.二级审批拒绝
3.全流程结束
使用责任链解决这类问题代码的可读性和可维护性都很高,后期需要插入审批直接维护枚举类即可,像权限控制、过滤器拦截器这些都是可以用这种方式实现,最后还是要提醒一下:也不要为了使用而使用,结合业务场景选择,如果本身业务就不复杂强行使用这个模式反而适得其反,给自己增加工作量